拓扑排序

Posted Luke_Ye

tags:

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

将DAG图转化为顺序排列的形式

可应用于DP求最长路、基于两两优劣关系求排名等题型。

前向星版代码:

#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
#define N 505
using namespace std;
int n,m,sum,cnt,flag;
int deg[N];
int head[N];
struct Node
{
    int v,next;
};
struct cmp
{
    bool operator()(int a,int b)
    {
        return a>b;
    }
};
Node edge[N<<1];
void print(int num)
{
    if(flag==0)
        printf("%d",num),flag=1;
    else
        printf(" %d",num);
}
void topoSort(int n)
{
    priority_queue<int,vector<int>,cmp> q;
    for(int i=1;i<=n;i++)
        if(deg[i]==0)
            q.push(i),deg[i]--;
    while(!q.empty())
    {
        int u=q.top();
        q.pop(),print(u);
        sum--;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            Node e=edge[i];
            deg[e.v]--;
        }
        for(int i=1;i<=n;i++)
            if(deg[i]==0)
                q.push(i),deg[i]--;
    }
}
void ini()
{
    for(int i=1;i<=n;i++)
        deg[i]=0,head[i]=-1,flag=0;
    cnt=0,sum=n;
}
void add(int u,int v)
{
    deg[v]++;
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int main(int argc, const char * argv[]) {
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int a,b;
        ini();
        for(int i=0;i<m;i++)
            scanf("%d%d",&a,&b),add(a,b);
        topoSort(n);
        puts("");
    }
    return 0;
}

邻接表版代码:

#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
#define N 505
using namespace std;
int n,m,sum,cnt,flag;
int deg[N];
vector<int> g[N];
struct cmp
{
    bool operator()(int a,int b)
    {
        return a>b;
    }
};
void print(int num)
{
    if(flag==0)
        printf("%d",num),flag=1;
    else
        printf(" %d",num);
}
void topoSort(int n)
{
    priority_queue<int,vector<int>,cmp> q;
    for(int i=1;i<=n;i++)
        if(deg[i]==0)
            q.push(i),deg[i]--;
    while(!q.empty())
    {
        //if(q.size()>1) 可用于判断是否充分排序。
        //如果有多个入度为0的同时入队,说明他们之间没有明确的排序条件。
        int u=q.top();
        q.pop(),print(u);
        sum--;//可用于判断是否有冲突,如果有冲突,就会导致两者或者已上的节点入度无法降为0
        for(int i=0;i<g[u].size();i++)
        {
            int e=g[u][i];
            deg[e]--;
        }
        for(int i=1;i<=n;i++)
            if(deg[i]==0)
                q.push(i),deg[i]--;
    }
}
void ini()
{
    for(int i=0;i<=n;i++)
        deg[i]=0,flag=0,g[i].clear();
    cnt=0,sum=n;
}
void add(int u,int v)
{
    deg[v]++;
    g[u].push_back(v);
}
int main(int argc, const char * argv[]) {
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int a,b;
        ini();
        for(int i=0;i<m;i++)
            scanf("%d%d",&a,&b),add(a,b);
        topoSort(n);
        puts("");
    }
    return 0;
}

 

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

拓扑排序代码:

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

UVA10305 拓扑排序

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

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

拓扑排序之变量序列代码