hiho215 Circle Detect
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
You are given a directed graph G which has N nodes and M directed edges. Your task is to detect whether it contains any circle.
输入
The first line contains an integer T denoting the number of test cases. (1 <= T <= 5)
For each test case the first line contains two integers N and M. (1 <= N, M <= 100000)
Then follows M lines. Each contains two integers u and v denoting there is an edge from u to v. (1 <= u, v <= N)
输出
For each test case output "YES" or "NO" denoting whether there is a circle in the graph.
样例输入
2 5 5 1 2 2 3 4 5 5 4 4 2 3 2 1 2 2 3
样例输出
YES NO
题意分析:
1.题是什么?
这道题很直白,就是给你一个有向图,让你判断是否存在环.
2.思路
最开始想成并查集去了,后来发现是有向图.....如果是无向图可以已并查集快速搞定,有向图不行,下面举出特例:
对于这个最简单的有向图,明显不该被认定为环,然而如果这四条边是无向边,自然这是个环.
然后是思路,对每个结点做dfs,dfs的同时做标记,如果发现dfs到了刚才走过的结点,自然就成环了,关键在于dfs回溯时要对标记做一个清除,这样才能正确.
ac代码:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
const int maxn=100005;
vector<int> children[maxn]; //children[i]存储i的所有子节点
int flag[maxn]; //flag[i]为0表示未被dfs过,为1表示刚刚经过过它,为2表示是已经dfs完所有子节点无环的安全结点
bool dfs(int pos){
flag[pos]=1;
int num=children[pos].size();
for(int i=0;i<num;i++){
int t=children[pos][i];
if(flag[t]==1) return true;
if(flag[t]==0&&dfs(t)) return true;
}
flag[pos]=2;
return false;
}
void solve(){
int t,n,m,t1,t2;
bool existcircle;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
//初始化
for(int i=1;i<=n;i++){
children[i].clear();
flag[i]=0;
}
existcircle=false;
//读入
for(int i=0;i<m;i++){
scanf("%d%d",&t1,&t2);
children[t1].push_back(t2);
}
//dfs
for(int i=1;i<=n;i++){
if(flag[i]==0){
if(dfs(i)){
existcircle=true;
break;
}
}
}
//输出
if(existcircle) printf("YES\n");
else printf("NO\n");
}
}
int main(){
solve();
return 0;
}