hihocoder 1174 [BFS /拓扑排序判断是否有环]

hihocoder 1174
[算法]:

  1. 计算每一个点的入度值deg[i],这一步需要扫描所有点和边,复杂度O(N+M)。

  2. 把入度为0的点加入队列Q中,当然有可能存在多个入度为0的点,同时它们之间也不会存在连接关系,所以按照任意顺序加入Q都是可以的。

  3. 从Q中取出一个点p。对于每一个未删除且与p相连的点q,deg[q] = deg[q] - 1;如果deg[q]==0,把q加入Q。

  4. 不断重复第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;
}

猜你喜欢

转载自www.cnblogs.com/Roni-i/p/9167620.html