Street Race[USACO]

 

第一问,判断各节点被删除之后,是否可以从起点到终点,如不可以,则满足要求。

 

第二问在第一问基础上,我用的bfs,判断是否成功:将图从当前节点分割成两部分(如果只分成了一部分,则为失败),是否所有边都为内部边,若是则当前节点满足。

 

/*
ID: zhangyc1
LANG: C++
TASK: race3
*/
#include <fstream>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;

ofstream fileout("race3.out");
int N = 0;
int arrLink[50][50], arrSize[50];
int nIndexMoved = -1;
bool arrVisited[50], arrIsRightPart[50];

void prepairData()
{
    memset(arrLink, 0, sizeof(arrLink));
    memset(arrSize, 0, sizeof(arrSize));
    ifstream filein("race3.in");
    int nNum;
    while (filein >> nNum && nNum != -1)
    {
        while (nNum != -2)
        {
            arrLink[N][arrSize[N]] = nNum;
            filein >> nNum;
            arrSize[N]++;
        }
        N++;
    }
    filein.close();
}

bool dfs(int nIndex)
{
    if (nIndex == N - 1)
    {
        return true;
    }

    arrVisited[nIndex] = true;
    for (int i = 0; i < arrSize[nIndex]; i++)
    {
        if (!arrVisited[arrLink[nIndex][i]] && arrLink[nIndex][i] != nIndexMoved)
        {
            if(dfs(arrLink[nIndex][i]))
                return true;
        }
    }
    return false;
}

bool Partition(int nIndex)
{
    memset(arrIsRightPart, 0, sizeof(arrIsRightPart));
    queue<int> q;
    q.push(nIndex);
    int nRight = 0;
    while (!q.empty())
    {
        int nTemp = q.front();
        q.pop();
        arrIsRightPart[nTemp] = true;
        nRight++;
        for (int i = 0; i < arrSize[nTemp]; i++)
        {
            if(!arrIsRightPart[arrLink[nTemp][i]])
                q.push(arrLink[nTemp][i]);
        }
    }
    // 判断图是否只划分出了一部分
    if (nRight == N || nRight == 1)
        return false;

    for (int i = 0; i < N; i++)
    {
        if (i == nIndex)
            continue;
        for (int j = 0; j < arrSize[i]; j++)
        {
           if (arrLink[i][j] == nIndex)
               continue;
           if (arrIsRightPart[i] ^ arrIsRightPart[arrLink[i][j]])
           {
               return false;
           }
        }
    }
    return true;
}

void process()
{
    int nCount = 0, arrCross[50];
    for (int i = 1; i < N -1; i++)
    {
        nIndexMoved = i;
        memset(arrVisited, 0, sizeof(arrVisited));
        if (!dfs(0))
        {
            arrCross[nCount++] = i;
        }
    }

    int nCount2 = 0, arrCross2[50];
    for (int i = 0; i < nCount; i++)
    {
        if (Partition(arrCross[i]))
        {
            arrCross2[nCount2++] = arrCross[i];
        }
    }
    fileout << nCount;
    for (int i = 0; i < nCount; i++)
    {
        fileout << " " << arrCross[i];
    }
    fileout << endl;
    fileout << nCount2;
    for (int i = 0; i < nCount2; i++)
    {
        fileout << " " << arrCross2[i];
    }
    fileout << endl;
}

int main(){
    prepairData();
    process();
    fileout.close();
    return 0;
}

  

转载于:https://www.cnblogs.com/doublemystery/archive/2013/04/11/3015071.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值