HDU-4857-逃生

题目链接 http://hdu.hustoj.com/showproblem.php?pid=4857

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

 

逆向拓扑排序+优先队列

这题要求编号小的尽量在前面,要注意与字典序不同

样例给的不经典,可以看这样一个例子:

如图,用优先队列拓扑排序得到的是 3 5 6 4 1 7 8 9 2 0,但正确答案应该是 6 4 1 3 9 2 5 7 8 0。

在错误的答案中,编号小的(1)显然不在编号大的(2)前面。不满足数值小的尽量排在前面的要求。

我们发现,每一次都取入度为0的并且最小的点输出不能使得最小的点排在尽可能靠前的位置,也就是局部最优不能使得全局最优。

这里我们可以得到“前面的小的不一定排在前面,但是有一点后面大的一定排在后面”。

所以我们要做的就是:反向建图+逆序输出

建立一个反图,跑一遍字典序最大的拓扑排序,然后倒过来输出就可。


 

啊对,用 cin和cout 就会 Time Limit Exceeded 。好几遍了。。。。。。


 

放AC代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <queue>
 6 #define maxn 30005
 7 using namespace std;
 8 
 9 int t,n,m;
10 int in[maxn];
11 vector<int>edge[maxn];
12 
13 int main()
14 {
15     scanf("%d",&t);
16     while(t--)
17     {
18         priority_queue<int>q;
19         memset(in,0,sizeof(in));
20         vector<int>res;
21         int u,v;
22 
23         scanf("%d%d",&n,&m);
24         for(register int i=1; i<=n; i++)
25             edge[i].clear();
26         for(register int i=1; i<=m; i++)
27         {//反向建图
28             scanf("%d%d",&u,&v);
29             in[u]++;
30             edge[v].push_back(u);
31         }
32         for(register int i=1; i<=n; i++)
33         {//将反图中入度为0的点加入队列
34             if(in[i]==0) q.push(i);
35         }
36         while(!q.empty())
37         {
38             u=q.top();
39             res.push_back(u);
40             q.pop();
41             for(register int i=0; i<edge[u].size(); i++)
42             {
43                 v=edge[u][i];
44                 in[v]--;
45                 if(in[v]==0) q.push(v);
46             }
47         }
48         for(register int i=res.size()-1; i>=0; i--)
49         {
50             if(i==res.size()-1) printf("%d",res[i]);
51             else printf(" %d",res[i]);
52         }
53         puts("");
54     }
55     return 0;
56 }

 

posted @ 2022-05-19 21:46  爱吃虾滑  阅读(27)  评论(0)    收藏  举报