1. 程式人生 > >拓撲排序(判斷是否是有向無環圖)

拓撲排序(判斷是否是有向無環圖)

要進行拓撲排序之前,該圖要是有向無環圖。

排序方法:

1、從有向圖中選取一個沒有前驅的頂點,並輸出之

;2、從有向圖中刪去此頂點以及所有以它為尾的弧;

3、重複上述兩步,直至圖空,或者圖不空但找不到無前驅的頂點為止。

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int maxn=100001;
const int inf=1<<29;
int e,head[maxn],pnt[maxn],nxt[maxn];
int cnt_in[maxn],cnt_out[maxn];
bool vis[maxn];
int n,m,k;
void AddEdge(int u,int v)
{
    pnt[e]=v;nxt[e]=head[u];head[u]=e++;
}
int main()
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        scanf("%d%d",&n,&m);
        e=0;
        memset(head,-1,sizeof(head));
        memset(cnt_in,0,sizeof(cnt_in));
        memset(cnt_out,0,sizeof(cnt_out));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            AddEdge(u,v);
            cnt_out[u]++;
            cnt_in[v]++;
        }
        /*for(int i=1;i<=n;i++)
        {
            printf("%d :",i);
            printf("%d %d\n",cnt_in[i],cnt_out[i]);
        }*/
        int cnt=0;
        int kj[maxn];
        while(1)
        {
            int f=0;
            for(int u=1;u<=n;u++)
            {
                if(cnt_in[u]==0&&!vis[u])
                {
                    f=1;
                    for(int i=head[u];i!=-1;i=nxt[i])
                    {
                        cnt_in[pnt[i]]--;
                    }
                    kj[cnt++]=u;
                    vis[u]=1;
                }
            }
            if(cnt==n||f==0)
                break;
        }
        int k2=0;
        for(int i=1;i<=n;i++)//如果所有的數字的入度都為0,代表這是一個無環圖。
            if(vis[i]==0)
             k2=1;
        if(k2==1)
        puts("Wrong");
        else
            puts("Correct");

    }
    return 0;
}
而拓撲排序 只要將上面的陣列kj[]從小到大輸出即可。

 for(int i=0;i<cnt;i++)
            printf("%d ",kj[i]);