POJ3687 反向拓扑排序

Posted mj-liylho

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3687 反向拓扑排序相关的知识,希望对你有一定的参考价值。

Labeling Balls
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 16032   Accepted: 4713

Description

Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that:

  1. No two balls share the same label.
  2. The labeling satisfies several constrains like "The ball labeled with a is lighter than the one labeled with b".

Can you help windy to find a solution?

Input

The first line of input is the number of test case. The first line of each test case contains two integers, N (1 ≤ N ≤ 200) and M (0 ≤ M ≤ 40,000). The next M line each contain two integers a and bindicating the ball labeled with a must be lighter than the one labeled with b. (1 ≤ a, b ≤ N) There is a blank line before each test case.

Output

For each test case output on a single line the balls‘ weights from label 1 to label N. If several solutions exist, you should output the one with the smallest weight for label 1, then with the smallest weight for label 2, then with the smallest weight for label 3 and so on... If no solution exists, output -1 instead.

Sample Input

5

4 0

4 1
1 1

4 2
1 2
2 1

4 1
2 1

4 1
3 2

Sample Output

1 2 3 4
-1
-1
2 1 3 4
1 3 2 4

Source

 

题意:

给定N个球,编号分别是1-N,重量也是1-N,任意两个球的编号和重量不相等。

给定一些约束:类似编号为a的球比编号为b的球轻,要求输出的答案必须让编号为1的球重量尽量轻,接着是编号为2的球重量尽量轻,一直到编号为N的球尽量轻。

思路:

原命题:编号小的球重量尽量轻。   

逆否命题:重量大的球编号尽量大,逆向拓扑排序即可。

PS:数据存在重边,自环等。。

代码:

 1 #include"bits/stdc++.h"
 2 
 3 #define db double
 4 #define ll long long
 5 #define vl vector<ll>
 6 #define ci(x) scanf("%d",&x)
 7 #define cd(x) scanf("%lf",&x)
 8 #define cl(x) scanf("%lld",&x)
 9 #define pi(x) printf("%d
",x)
10 #define pd(x) printf("%f
",x)
11 #define pl(x) printf("%lld
",x)
12 #define rep(i, a, n) for (int i=a;i<n;i++)
13 #define per(i, a, n) for (int i=n-1;i>=a;i--)
14 #define fi first
15 #define se second
16 using namespace std;
17 typedef pair<int, int> pii;
18 const int N   = 1e5 + 5;
19 const int mod = 1e9 + 7;
20 const int MOD = 998244353;
21 const db  PI  = acos(-1.0);
22 const db eps  = 1e-10;
23 const int inf = 0x3f3f3f3f;
24 const ll INF  = 0x3fffffffffffffff;
25 
26 int n,m,cnt;
27 bool mp[205][205];
28 int du[N],head[N];
29 int a[205];
30 struct P{int to,nxt;}e[N];
31 void add(int u,int v){
32     e[cnt].to=v;
33     e[cnt].nxt=head[u];
34     head[u]=cnt++;
35 }
36 void topsort()
37 {
38     int k=n;
39     priority_queue<int>q;
40     for(int i=1;i<=n;i++) if(!du[i]) q.push(i);
41     while(!q.empty())
42     {
43         int tmp=q.top();
44         q.pop();
45         a[tmp]=k--;
46         for(int i=head[tmp];~i;i=e[i].nxt){
47             int v=e[i].to;
48             du[v]--;
49             if(!du[v]) q.push(v);
50         }
51     }
52     if(k!=0) printf("-1
");
53     else
54     {
55         for(int i=1;i<=n;i++)
56             printf("%d%c",a[i],i==n?
: );
57     }
58 }
59 void init()
60 {
61     memset(mp,0,sizeof(mp));
62     memset(a,0,sizeof(a));
63     memset(head,-1,sizeof(head));
64     memset(du,0,sizeof(du));
65     cnt=0;
66 }
67 int main()
68 {
69     int t;
70     ci(t);
71     while(t--)
72     {
73         init();
74         scanf("%d%d",&n,&m);
75         while(m--)
76         {
77             int x,y;
78             scanf("%d%d",&x,&y);
79             if(mp[x][y]==1) continue;
80             mp[x][y]=1,add(y,x);//反向边
81             du[x]++;
82         }
83         topsort();
84     }
85     return 0;
86 }

 

以上是关于POJ3687 反向拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3687 Labeling Balls(反向拓扑+贪心思想!!!非常棒的一道题)

POJ 3687:Labeling Balls(优先队列+拓扑排序)

POJ 3687 Labeling Balls(特殊的拓扑排序)

POJ - 3687 Labeling Balls (拓扑排序)

POJ-3687 Labeling Balls(拓扑)

拓扑排序+不是字典序的优先级排列(POJ3687+HDU4857)