题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285
题目给出一些点对之间的先后顺序,要求给出一个字典序最小的拓扑排列。对于拓扑排序的问题,我们有DFS和BFS都能够解决,但是问题是DFS只能处理上一层结点和下一层结点相对于根节点之间的距离,也就是说深度就是他们之间的先后顺序,对于同一层的,是没有先后顺序的,但是BFS可以处理同一层之间的先后关系,所以我们考虑用BFS进行遍历,并且将原始BFS求拓扑排序中的队列变成优先队列。这样我们就能在每一层中优先选择字典序小的结点先输出。
代码如下:
1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef unsigned int ui;
4 typedef long long ll;
5 typedef unsigned long long ull;
6 #define pf printf
7 #define mem(a,b) memset(a,b,sizeof(a))
8 #define prime1 1e9+7
9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x)
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define mp(a,b) make_pair((a),(b))
17 #define P pair<int,int>
18 #define dbg(args) cout<<#args<<":"<<args<<endl;
19 #define inf 0x3f3f3f3f
20 const int maxn=505;
21 int n,m,t;
22 inline int read(){
23 int ans=0,w=1;
24 char ch=getchar();
25 while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
26 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
27 return ans*w;
28 }
29 struct node{
30 int u,v;
31 }p[maxn];
32 int e;
33 int vis[maxn][maxn],head[maxn],nxt[maxn],in[maxn],num[maxn];//in表示入度
34 void init()
35 {
36 e=0;
37 mem(vis,0);mem(head,-1);mem(nxt,-1);mem(in,0);
38 mem(num,0);//排名信息置零
39 }
40 void addedge(int u,int v)
41 {
42 p[e].u=u;
43 p[e].v=v;
44 nxt[e]=head[u];
45 head[u]=e++;
46 }
47 void topsort()
48 {
49 priority_queue<int,vector<int> ,greater<int> > q;//最小堆
50 f(i,1,n)
51 {
52 if(in[i]==0)q.push(i);//将入度为零的点按照字典序排在优先队列中
53 }
54 int t=0,id;//用BFS对付topsort时从队列中出来的点的顺序实际上就是topsort完成之后应该有的排序
55 while(!q.empty())
56 {
57 num[t++]=id=q.top();
58 q.pop();
59 for(int i=head[id];~i;i=nxt[i])//扫描从这一点出发的所有的边
60 {
61 in[p[i].v]--;//所到的点的入度减一
62 if(in[p[i].v]==0)q.push(p[i].v);//将入度为0的点归入优先队列
63 }
64 }
65 //将所有的点都扫描过之后,由于一定存在拓扑序,所以直接输出结果
66 pf("%d",num[0]);
67 f(i,1,n-1)pf(" %d",num[i]);
68 pf("\n");
69 }
70 int main()
71 {
72 //freopen("input.txt","r",stdin);
73 //freopen("output.txt","w",stdout);
74 std::ios::sync_with_stdio(false);
75 while(scanf("%d%d",&n,&m)!=EOF)
76 {
77 init();
78 int a,b;
79 f(i,1,m)
80 {
81 a=read(),b=read();
82 if(!vis[a][b])//保证两条边之间的只有一条有向边,否则出入度就会发生变化,导致错误
83 {
84 addedge(a,b);
85 vis[a][b]=1;
86 in[b]++;
87 }
88 }
89 topsort();
90 }
91
92 }
来源:https://www.cnblogs.com/randy-lo/p/12577618.html