[Description]:拓扑排序,并且输出最小字典序的一个可能顺序,采用最小优先级队列可以保证按最小字典序输出。
[Input]:
输入第一行包含两个数n, m分别表示有向无环图的点数和边数。
接下来m行,每行两个数ai, bi,表示图中存在一条ai指向bi的有向边。
[Output]:输出n个数,每个数用空格隔开,表示该图的拓扑序。
拓扑排序:
1.统计每个结点的入度,将度为0的结点编号放入队列(此题放入优先队列中)中。
2.进行循环:
①取出队头结点,视作边的起点。
②删除与该点相连的边,即将这个图中的该边另一个结点(即终点)的入度减一。
③如果减一以后,终点的入度变为了0,那么将终点的编号入队列。
④判断队列是否为空,若不为空回到①。
优先级队列:
stl:priority_queue<int,vector<int>,greater<int> > q;
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=100005;
int n,m;
int a,b;
struct edge
{
int to,next;
}e[maxn];
int in[maxn];//记录入度
int head[maxn];
int k;
priority_queue<int,vector<int>,greater<int> > q;
void add(int u,int v)
{
k++;
e[k].to=v;
e[k].next=head[u];
head[u]=k;
}
void topp()
{
for(int i=1;i<=n;i++)
{
if(in[i]==0)//入度为0
{
q.push(i);//入队
in[i]--;
}
}
while(!q.empty())
{
int p=q.top();
q.pop();
printf("%d ",p);
int p1=head[p];
while(p1!=0)
{
in[e[p1].to]--;
if(in[e[p1].to]==0) q.push(e[p1].to);
p1=e[p1].next;
}
}
}
int main()
{
freopen("topsort.in","r",stdin);
freopen("topsort.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&a,&b);
add(a,b);
in[b]++;
}
topp();
return 0;
}</span>