hihocoder 1174 [BFS /拓扑排序判断是否有环]
[hihocoder 1174](http://hihocoder.com/problemset/problem/1174)
[算法]:
1. 计算每一个点的入度值deg[i],这一步需要扫描所有点和边,复杂度O(N+M)。
-
把入度为0的点加入队列Q中,当然有可能存在多个入度为0的点,同时它们之间也不会存在连接关系,所以按照任意顺序加入Q都是可以的。
-
从Q中取出一个点p。对于每一个未删除且与p相连的点q,deg[q] = deg[q] - 1;如果deg[q]==0,把q加入Q。
-
不断重复第3步,直到Q为空。
把入度为0的点加入队列Q中,当然有可能存在多个入度为0的点,同时它们之间也不会存在连接关系,所以按照任意顺序加入Q都是可以的。
从Q中取出一个点p。对于每一个未删除且与p相连的点q,deg[q] = deg[q] - 1;如果deg[q]==0,把q加入Q。
不断重复第3步,直到Q为空。
最后剩下的未被删除的点,也就是组成环的点了。
[代码]:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n,m,u,v,num;
int indeg[maxn];
vector<int> G[maxn];
queue<int> q;
bool topSort()
{
while(!q.empty()) q.pop(); //清空队列
num=0; //记住一定要将可以删去的点清0
for(int i=1;i<=n;i++) if(!indeg[i]) q.push(i); //若一开始的先驱课程没有入度,那么压入队列
while(!q.empty())
{
int now=q.front(); //取出队首
q.pop();
num++; //删点++
for(int i=0; i<G[now].size(); i++) //遍历这个被删去的点的其他相邻结点
{
int nxt = G[now][i]; //相邻点
if( --indeg[nxt] == 0 ) q.push(nxt); //if判断的是:相邻结点的入度--,若为0了,就压入队列作为 下一个要删去的点
}
}
if(num == n) return true; //若点都删去了 说明没有环存在
else return false;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(indeg,0,sizeof(indeg));
for(int i=1;i<=n;i++) G[i].clear();
cin>>n>>m;
while(m--)
{
cin>>u>>v;
G[u].push_back(v); //将有向边u指向v
indeg[v]++; //v的入度++
}
if(topSort()) puts("Correct"); //无环则ojbk
else puts("Wrong");
}
return 0;
}