拓扑排序

处理何种问题:虽说是排序,但是主要作用是判断有向图是否有环。

 

性能:时间复杂度为O(E),E为边的个数。

 

原理:每次找入度为0的点入栈,然后将与此相连的节点入度减1;重复以上步骤,直到栈中为空。记录弹出节点次数,如果次数与节点总数相同,及无环,否则,有环的存在。(证明的时候注意,如果一个点的入度已变为0,则再也不会有其他点能到达它)

 

实现步骤:建图(vector)+ 栈(队列) 模拟

 

备注:略

 

输入样例解释

2 2 //n 节点个数,m 边的个数

1 2 //由a 到 b

2 1

3 2

1 2

1 3

 

输出样例解释:

Cycle //有环

Not Cycle //无环

 

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<Stack>
#include<vector>
using namespace std;

const int MaxN=10010;
vector<int>edge[MaxN];
stack<int>S;

int n,m,ctor;
int ind[MaxN];//入度

void init()
{
    ctor=0;
    memset(ind,0,sizeof(ind));
    for(int i=0;i<=n;++i)
    {
        edge[i].clear();
    }
    while(!S.empty())
    {
        S.pop();
    }
}

void solve()
{
    for(int i=1;i<=n;++i) //节点必须由1开始
    {
        if(ind[i]==0)
            S.push(i);
    }

    while(!S.empty())
    {
        int temp=S.top();
        S.pop();
        ++ctor;
        int len=edge[temp].size();
        for(int i=0;i<len;++i)
        {
            --ind[edge[temp][i]];
            if(ind[edge[temp][i]]==0)
                S.push(edge[temp][i]);
        }
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init();
        int a,b;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            ++ind[b];
            edge[a].push_back(b);
        }
        solve();

        if(ctor==n)
            printf("Not Cycle
");
        else
            printf("Cycle
");

    }

    return 0;
}

  

原文地址:https://www.cnblogs.com/l1l1/p/9677294.html