拓扑排序

将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]--;
            if (deg[e.v] == 0) q.push(e.v), deg[e.v]--;
            
        }
    }
}
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]--;
            if (deg[e.v] == 0) q.push(e.v), deg[e.v]--;
        }
        
    }
}
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;
}
原文地址:https://www.cnblogs.com/LukeStepByStep/p/5957001.html