描述
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
题意:
给一个n个点m条边的有向图,判断该图有没有环
思路:
经典的题,直接用拓扑排序来做算法如下:
算法思想
1、在AOV网络中选一个没有直接前驱的顶点, 并入栈(或者输出);
2、从图中删去该顶点, 同时删去所有它发出的有向边;
3、重复以上步骤, 直到
◆ 全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;
◆ 或者图中还有未输出的顶点,但已跳出处理循环。这说明图中还剩下一些顶点,它们都有直接前驱,再也找不到没有前驱的顶点了。这时AOV网络中必定存在有向环。
#include <iostream>
#include <stack>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1e5+5;
struct edge
{
int to;
};
vector<edge>G[maxn];
int in[maxn];
int n,m;
bool judge()
{
stack<int>st;
for (int i = 1; i <= n; ++i) {
if (in[i] == 0) {
st.push(i);
}
}
int cnt = 0;
while(!st.empty()) {
auto tmp = st.top();
st.pop();
++cnt;
for (int i = 0; i < G[tmp].size(); ++i) {
auto now = G[tmp][i];
--in[now.to];
if (in[now.to] == 0) {
st.push(now.to);
}
}
}
if (cnt == n) return true;
return false;
}
int main()
{
int t,u,v;
cin >> t;
while(t--) {
cin >> n >> m;
memset(in,0,sizeof(in));
for (int i = 0; i < maxn; ++i) G[i].clear();
for (int i = 0 ; i < m; ++i) {
cin >> u >> v;
++in[v];
edge tmp;
tmp.to = v;
G[u].push_back(tmp);
}
if (judge()) cout << "NO" << endl;
else
cout << "YES" << endl;
}
return 0;
}