Poj 3687 -- Labeling Balls

Labeling Balls
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9070   Accepted: 2451

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 b indicating 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


思路:这是一道很有意思的题。由于今天刚接触拓扑排序,所以做这个题感觉非常非常吃力。之所以说他有意思,是因为这个题灵活性很大,
除了要逆向建图,还需要注意很多地方,比如说输出的是球的重量和重边问题等等。可以举个例子来说明我的思路:
5 4
5 1
4 2
1 3
2 3
给出这组数据:用一数组标记是否重边,且用数组建立数与数之间的联系。比如输入a,b拿后面两对 1 3 2 3,可以令s[1][3]=1.s[2][3]=1
这样不仅可以标记已经存在,还可以说明3 与1 2存在关系。然后in[a]++, in[]表示入度。
然后就可以建图了。不断寻找入度为零的数加进优先队列,每出一个元素,与它有联系的元素的入度均减一,出去的这个元素重量肯定是最大的,然后再找入度为零的元素进队列
再出队列。此元素(即球的标号)的重量是第二大的。不断进出直到队列为空。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <queue>
 5 using namespace std;
 6 int in[250],s[250][250],weight[250];
 7 void slove(int n)
 8 {
 9     priority_queue<int>que;
10     int i,g=n;
11     for(int i=1; i<=n; i++){
12         if(in[i]==0) que.push(i);
13     }
14     while(!que.empty()){
15         int t=que.top();
16         weight[t]=g--;
17         que.pop();
18         for(int i=1; i<=n; i++){
19             if(s[t][i] && --in[i]==0){
20                 que.push(i);
21             }
22         }
23     }
24     for(i=1; i<=n; i++){
25         if(!weight[i]){
26             printf("-1
");
27             break;
28         }
29     }
30     if(i<=n) return ;
31     int flag=0;
32     for(int i=1; i<=n; i++){
33         if(flag) printf(" ");
34         printf("%d",weight[i]);
35         flag=1;
36     }
37     printf("
");
38 }
39 int main()
40 {
41     int cas,n,m,a,b;
42     scanf("%d",&cas);
43     while(cas--){
44         memset(s,0,sizeof(s));
45         memset(in,0,sizeof(in));
46         memset(weight,0,sizeof(weight));
47         scanf("%d%d",&n,&m);
48         for(int i=0; i<m; i++){
49             scanf("%d%d",&a,&b);
50             if(!s[b][a]){
51                 s[b][a]=1;
52                 in[a]++;
53             }
54         }
55         slove(n);
56     }
57     return 0;
58 }





Do one thing , and do it well !
原文地址:https://www.cnblogs.com/ubuntu-kevin/p/3226475.html