HDU 4857 逃生 拓扑排序好题 第一次做CLJ出的题

          逃生



Problem Description
糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。

现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。

负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。

那么你就要安排大家的顺序。我们保证一定有解。
 
Input
第一行一个整数T(1 <= T <= 5),表示测试数据的个数。
然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。

然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。
 
Output
对每个测试数据,输出一行排队的顺序,用空格隔开。
 
Sample Input
1
5 10
3 5
1 4
2 5
1 2
3 4
1 4
2 3
1 5
3 5
1 2
 
Sample Output
1 2 3 4 5
 
 
 
 
这道题刚开始理解错题意了,这道题不是保证字典序,而是要最小的数字尽量在前面。
比如要1在不矛盾的情况下尽量在前面,然后2尽量在前面......
 
我刚开始:
要最小的尽量在前面,那就用priority_queue,然后从小到大,拓扑排序
但是这样只能保证拿出来的数字在当前队列中是最小的,而不能保证最后最小的一定在尽量前的位置。
比如:
较小,较大,最小,然后较大有连接最小的边,这样我输出是:较小,较大,最小,
但更优的情况是:较大,最小,较小
因为这样最小在更前的位置了。
 
那怎么做呢?
我是看了题解才知道的:
优先级:大到小的priority_queue
逆向建图+反向输出结果
 
 
为什么呢?
要最小的尽量前,我们就把最小的尽量放在后面,则priority_queue的优先级:从大到小,然后反向输出,
但是反向输出后的序列又要满足拓扑排序的规律,所以我们先要逆向建图。
这样反向输出后不就相当于正向了吗?
 
通过这道题自己也是学习了好多。
 
 
 
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 #include<vector>
 6 
 7 using namespace std;
 8 
 9 const int maxn=30000+5;
10 
11 int f[maxn];
12 int inde[maxn];
13 vector<int>edge[maxn];
14 int tot;
15 
16 void solve(int n)
17 {
18     tot=1;
19 
20     priority_queue<int>que;
21     while(!que.empty())
22         que.pop();
23 
24     for(int i=1;i<=n;i++)
25     {
26         if(inde[i]==0)
27             que.push(i);
28     }
29 
30     while(!que.empty())
31     {
32         int u=que.top();
33         f[tot++]=u;
34         que.pop();
35 
36         for(int i=0;i<edge[u].size();i++)
37         {
38             int v=edge[u][i];
39             inde[v]--;
40             if(inde[v]==0)
41                 que.push(v);
42         }
43     }
44 
45     for(int i=tot-1;i>1;i--)
46         printf("%d ",f[i]);
47     printf("%d
",f[1]);
48 
49     return ;
50 }
51 
52 int main()
53 {
54     int test;
55     scanf("%d",&test);
56 
57     while(test--)
58     {
59         int n,m;
60         scanf("%d%d",&n,&m);
61 
62         memset(inde,0,sizeof(inde));
63         for(int i=1;i<=n;i++)
64             edge[i].clear();
65 
66         int u,v;
67         for(int i=1;i<=m;i++)
68         {
69             scanf("%d%d",&u,&v);
70             edge[v].push_back(u);
71             inde[u]++;
72         }
73 
74         solve(n);
75     }
76 
77     return 0;
78 }
343ms
 
 
 
 
 
 
 

 

原文地址:https://www.cnblogs.com/-maybe/p/4492213.html