描述
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
解题:判断成环的模板题:
- 还没被DFS访问的点是白色的,初始时所有点都是白色的
- 如果点u已经被DFS访问过,但是u的子节点还未全部被访问到,那么把u染成灰色
- 如果点u以及u的子节点都被访问过了,从u回溯到u的父节点时,将u染成黑色
如果在DFS的过程中我们沿着有向边到达了一个灰色节点,则说明图中有环;如果从未到达过灰色节点,说明没有环。
#include <vector>
#include <cstdio>
#include <map>
#include <iostream>
#include <set>
#include <cstring>
using namespace std;
#define MMAX 100000
int color[MMAX + 10]; //1是灰色,0是白色,2是黑色
map<int, vector<int> > mmap;
int dfs(map<int, vector<int> > &mmap, int ma)
{
int ok = 1;
color[ma] = 1;
if (0 == mmap.count(ma)) {
color[ma] = 2;
return 1;
}
vector<int> prs = mmap[ma];
for (int i=0; i<prs.size(); ++i) {
if (0 == color[prs[i]]) {
ok = dfs(mmap, prs[i]);
if (!ok) break;
}
if (1 == color[prs[i]]) {
ok = 0;
break;
}
}
color[ma] = 2;
return ok;
}
int main()
{
int N, M,T;
int ma, pr;
cin>>T;
while (T--) {
cin >> N >> M;
for (int i=0; i<M; ++i) {
cin >> ma >> pr;
if (0 == mmap.count(ma)) {
vector<int> prs;
prs.push_back(pr);
mmap[ma] = prs;
}
else {
mmap[ma].push_back(pr);
}
}
memset(color, 0, sizeof(color));
int ok;
for (map<int, vector<int> >::iterator it = mmap.begin();
it != mmap.end();
++it) {
if (0 == color[it->first]) {
ok = dfs(mmap, it->first);
if (ok == 0) break;
}
}
if (ok)
cout << "NO" << endl;
else
cout << "YES" << endl;
mmap.clear();
}
return 0;
}