拓扑排序——杨子曰算法
要知道,如果你要用c++打出拓扑排序的代码,你先要学会c++语法和拓扑排序的原理,你要学会c++语法你先要学会基本数学和计算机基础知识(←Are U sure?),你要学会拓扑排序的原理,你先要学会计算机基础知识和栈的使用,那现在让一个什么都不会的人学会拓扑,请输出任意一种合法方案
拓扑排序不像我们平时对数组排序那样,它是对一个有向图排序,↑就像上面那个↑,我们可以对这样的问题建一个图,从可以先选的,连向后选的,比方说:
选完1才能选2,3
选完3才能选7
选完7才能选2
选完2,4才能选5
选完5才能选6
我们就可以建这样一张图:
我觉得地球人一看就能明白
这里我们要知道一个东东——入度,就是指向这个点的边的数量
这样一来,我们每次都佛系地选一个入度为0的点,再把它连出去的边全部删掉(其实就是把连到的那个点的入度-1),你可以把入度为0的点放到一个栈里,每次弹出一个,然后不停重复,完事
用↑上面那个图↑,我们来举个栗子(←不是错别字)
首先我们发现,入度为0的点只有1,把它输出并删掉
这样2的入度-1, 3的入度-1
我们又发现3的入度为0,我们把3输出并删掉
所以7的入度-1,4的入度-1
噢,我们发现现在有两个点的入度都为零了,全部压倒栈里,随便选一个删掉,比如7
现在2和4,都可以选,佛系选了2
这时,我们发现只有4能选了,选上
我们得到了最终的序列:1,3,7,2,4,5,6
OK,完事
于 XJZX 507机房
c++代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=50005,maxm=100005;
struct Edge{
int next,to;
}edge[maxm*2];
int n,m,nedge=0,inc[maxn],head[maxn],stk[maxn];//inc时入度
void addedge(int a,int b){
edge[nedge].to=b;
edge[nedge].next=head[a];
head[a]=nedge++;
}
int main(){
memset(head,-1,sizeof(head));
memset(inc,0,sizeof(inc));
scanf("%d%d",&n,&m);
while(m--){
int a,b;
scanf("%d%d",&a,&b);
addedge(b,a);
inc[a]++;
}
int top=0;
for (int i=1;i<=n;i++){
if (!inc[i]) stk[++top]=i;
}
while(top>0){
int x=stk[top--];
cout<<x<<' ';
for (int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].to;
if (!--inc[v]) stk[++top]=v;
}
}
return 0;
}
未经作者允许,严禁转载:https://blog.csdn.net/HenryYang2018/article/details/81041060