拓扑排序

Posted stungyep

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序相关的知识,希望对你有一定的参考价值。

拓扑排序

定义:拓扑排序是指在有向无环图中,将所有的结点进行排序,最终得出的序列称为拓扑序。

先来看一个模板代码:

#include<bits/stdc++.h>

using namespace std;
const int maxn=1e5+10;
int n,m,tot=0,head[maxn],seq[maxn],d[maxn];
struct node
{
    int nex,to;    
}edge[maxn];
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(seq,0,sizeof(seq));      //保存拓扑排序的结点
    memset(d,0,sizeof(d));          //保存每个结点的入度
}
void add(int from,int to)
{
    edge[++tot].to=to;
    edge[tot].nex=head[from];
    head[from]=tot;
}
void topsort()
{
    queue<int> q;           
    //如果编号要按顺序输出可有priority_queue<int,vector<int>,greater<int> >
    for(int i=1;i<=n;++i)
        if(!d[i])   q.push(i);
    int cnt=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        seq[++cnt]=u;
        for(int i=head[u];i!=-1;i=edge[i].nex)
            if(--d[edge[i].to]==0)   q.push(edge[i].to);
    }
    if(cnt!=n){
        printf("-1
");     //存在环
        return;
    }
    for(int i=1;i<=n;++i){
        printf("%d%c",seq[i],i==n?'
':' ');
    }
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        init();
        for(int i=1;i<=m;++i){
            int u,v;
            scanf("%d %d",&u,&v);
            add(u,v);
            d[v]++;
        }
        topsort();
    }
}

【题意】:有n个小球和m个要求,所有小球的重量在1~n之间,每个要求的格式为 a b 表示a比b轻,输出最小的字典序的组合。

思路:将所有小球的出度表示出来,用大根堆的优先队列将所有小球出度为0的球装进去,每次弹出一个编号最大的将剩余的最大重量给它贪心即可;show code:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>

using namespace std;
const int maxn=210;
int od[maxn],arr[maxn][maxn],T,n,m,seq[maxn];
void topsort()
{
    priority_queue<int> q;
    int tot=n;
    for(int i=1;i<=n;++i)
        if(od[i]==0)    q.push(i);
    while(!q.empty())
    {
        int u=q.top();
        q.pop();
        seq[u]=tot--;
        for(int i=1;i<=n;++i){
            if(arr[i][u]){
                od[i]--;
                if(od[i]==0)    q.push(i);
            }
        }
    }
    if(tot){
        printf("-1
");
        return;
    }
    for(int i=1;i<=n;++i){
        printf("%d%c",seq[i],i==n?'
':' ');
    }
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){
                arr[i][j]=0;
                od[i]=seq[i]=0;
            }
        }
        for(int i=1;i<=m;++i){
            int a,b;
            scanf("%d %d",&a,&b);
            if(!arr[a][b]){
                od[a]++;
                arr[a][b]=1;
            }
        }
        topsort();
    }
}

以上是关于拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

拓扑排序代码:

使用 C# 代码实现拓扑排序

UVA10305 拓扑排序

【数据结构】请写出以下AOV网的拓扑排序序列

数据结构问题~啥图可以进行拓扑排序~啥图不能进行拓扑排序?

拓扑排序之变量序列代码