DFS - 检查周期

时间:2014-06-27 17:38:53

标签: c++ depth-first-search

目标是找出无向,未加权的图形是否是树,即检查它是否包含后边缘。我使用了修改后的白灰黑色DFS算法(在Cormen中提供,并在此处提到的注释中提供:http://www.cs.cornell.edu/~wdtseng/icpc/notes/graph_part1.pdf

但不知何故,它不起作用。它运行了一次,但它导致了SPOJ的运行时错误(http://www.spoj.com/problems/PT07Y/)。

更新:我现在得到了这个问题的错误答案。该代码适用于示例测试用例。

失败的测试用例:

10 9

1 2

2 3

3 4

4 5

5 6

6 4

6 7

7 8

8 9

#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <vector>
#include <cstdlib>
using namespace std;

bool  M[10001][10001] = { 0 } ;
int color[10001] = { 0  };
long long int n;
bool answer=false;
void condition()
{
    cout<<"NO"<<endl;
    exit(0);
}
void condition2()
{
    cout<<"YES"<<endl;
    exit(0);
}

void dfs(int u, int p)
{
    color[u] = 1;
    for(int v=0; v < n; v++)
        {
            if(M[u][v] && v != p)
                {
                    if (color[v] == 0)
                        dfs(v, u);
                    else if (color[v]==1)
                    {
                         condition(); /* It has a backedge so it is not a tree, so print No */
                    }
                }
        }

    condition2(); /* It does not have backedge so it is not a tree so print YES */


}

int main()
{


long Z;
cin>>n>>Z;


// for(int i=0; i<n; i++) /* **Removed THIS nested loop to reduce runtime, successfully eliminated TLE** */
//     for(int j=0; j<n;j++)
//        M[i][j]=0;

for(int i=0; i < Z; i++)
{
    long temp1, temp2;
    cin>>temp1;
    cin>>temp2;
    temp1--;
    temp2--;

    M[temp1][temp2]=1;
    M[temp2][temp1]=1;

}


if(Z==n-1)
    dfs(0, -1);
else cout<<"NO"<<endl;

return 0;
}

1 个答案:

答案 0 :(得分:1)

图表是树,如果它已连接并且E = V-1,其中EV分别是边和节点的数量。因此,只要在启动DFS之前检查O(V),您就应该能够在E==V-1时间内解决它。

您是否可以针对图表测试您的程序,该图表是20000个节点的路径,编号为0的节点为叶子,并且存在从i到{{1}的边缘}}?请尝试在堆栈大小限制设置为SPOJ(8MB IIRC)的情况下运行它,并确保没有堆栈溢出。这是堆栈使用情况的最坏情况图。如果确实看到递归过深,则可以使用i+1来检查连接组件的数量是否为1.或者,您可以使用path compression,这将使您的运行时{{1}但是,但仍然足够快,足以适应1秒的限制。