hdu1532 用BFS求拓扑排序

题目链接: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("
"); 
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