拓扑排序
Posted dxy0310
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序相关的知识,希望对你有一定的参考价值。
拓扑排序:给一张有向无环图,求一个序列使得每一条边(x,y),x都出现在y之前
1.把所有预处理过的入度为0的节点加入队列中
2.每次取出队头,把队头加入答案序列尾部
3.把与队头相连的边的节点入度 -1,若减为0,加入队列
4.重复操作直至队列为空
若题目要求输出字典序最小或最大的拓扑排序 可以用优先队列
模板:
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<stack> #include<map> using namespace std; #define ll long long int n,m,cnt; int d[500000+10],deg[50000+100],head[1000000+10]; struct node { int to,next; }p[1000000+10]; void add(int x,int y) { cnt++; p[cnt].to=y; p[cnt].next=head[x]; head[x]=cnt; } void topsort() { cnt=0; queue<int>q; for(int i=1;i<=n;i++)//先将入度为0的点加入队列 if(deg[i]==0) q.push(i); while(q.size())//一直做到队列为空 { int u=q.front(); d[++cnt]=u;//将队头加入拓扑序列即输出答案中 q.pop(); for(int i=head[u];i;i=p[i].next)//遍历与堆头有边的点 //入度--,若减为0,把此点也加入队列中 { int v=p[i].to; if(--deg[v]==0) { q.push(v); } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); deg[b]++;//统计入度 add(a,b);//加边 } topsort(); if(cnt<n) { cout<<"No Answer!"<<endl;//该图为有向有环图 return 0; } for(int i=1;i<=n;i++)//输出拓扑序列 { cout<<d[i]<<" "; } cout<<endl; return 0; }
以上是关于拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章