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的优先级:从大到小, 然后反向输出,
但是反向输出后的序列又要满足拓扑排序的规律,所以我们先要逆向建图。
这样反向输出后不就相当于正向了吗?
 
通过这道题自己也是学习了好多。
 
 
 
HDU 4857 逃生 拓扑排序好题 第一次做CLJ出的题
 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\n",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

 

 
 
 
 
 
 
 

 

你可能感兴趣的:(HDU)