拓扑排序

58 阅读1分钟

每次都是把入度为0的点输出,当然输出之后会更新其他点的入度

样例

6 8
a b
a c
a d
c b
c d
d e
f d
f e

输出

a c b f d e

首先看一下我的暴力数组怎么做的吧,我相信你一样就能看懂

程序代码:

#include<stdio.h>
int a[110][110],b[110];
int main()
{
    char x,y;
    int i,j,k,n,m;
    scanf("%d%d",&n,&m);
    for(i=0;i<m;i++)
    {
        scanf(" %c %c",&x,&y);
        a[x-'a'][y-'a']++;
        b[y-'a']++;
    }
    for(k=0;k<n;k++)
    {
        for(i=0;i<n;i++)
            if(b[i]==0)
            {
                printf("%c ",i+'a');
                b[i]--;
                break;
            }
        if(i==n)
            break;
        for(j=0;j<n;j++)
            if(a[i][j]>0)
                b[j]--;
    }
    return 0;
}

刚刚的数组暴力有点浪费时间,其实我们只需用一个队列把入度为0的点存起来就行了,然后直接跑入度为0的点,更新与该点相连的点即可,当然了,很多时候要求输出按字典序什么的,这里用了优先队列

优先队列默认为是从大到小排序的,容器用的是vector

程序代码:

#include<stdio.h>
#include<queue>
using namespace std;

int a[110][110],b[110];
int main()
{
    priority_queue<int,vector<int>,greater<int> >q;//greater<int> 后有一个空格
    char x,y;
    int A;
    int i,n,m;
    scanf("%d%d",&n,&m);
    for(i=0;i<m;i++)
    {
        scanf(" %c %c",&x,&y);
        a[x-'a'][y-'a']++;
        b[y-'a']++;
    }

    for(i=0;i<n;i++)
        if(b[i]==0)
            q.push(i);

    while(!q.empty())
    {
        A=q.top();
        q.pop();
        printf("%c ",A+'a');
        for(i=0;i<n;i++)
            if(a[A][i]>0)
            {
                b[i]--;
                if(b[i]==0)
                    q.push(i);
            }
    }
    return 0;
}

如果需要判断是否满足拓扑排序,或者是否有环,定义一个数组,来存出来的入度为0的点,如果点数和为n则符合,反正不符