poj 3687 Labeling Balls - 贪心 - 拓扑排序

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 labelN. 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

  题目大意 找出原图的一个拓扑序,使得1尽量靠前,2尽量靠前....(注意输出的是第i个球的重量是第几小)。无解输出-1.

  我学长给出了一个正确性很显然的做法

  正向建图,把当前集合中的点中最小点找出来,然后再暴力统计有多少个点指向它,那么这些点一定在它之前,就可以将原DAG分成两部分递归处理。时间复杂度O(n(n + m))

Code

Click here to view

  还有个做法是反向建图,然后用大根堆去跑拓扑排序,最后输出的时候reverse一遍。虽然n变成了log2n,但是似乎正确性不是那么的显然。

  如果解释的话可以这么想,正向建图,跑小根堆先把小的取走,保证了在大的尽量在后面,但是无法保证小的尽量在前面,比如说下面这个建出来的DAG。

   这真是一个优美的反例。

  而反向建图跑大根堆,可以保证大的先被取走,自然小的就留在后面,reverse后,小的就跑到前面去了。

  下面给出一个并不太严谨的证明(有问题一定要指出来)

  假定存在一个更优的答案,那么第一处不相同的地方一定满足这个算法跑出来的值比这个答案大,因为前面的都相同,又因为都是1 ~ n的一个排列,那么意味着一定存在某个位置,这个答案比这个算法跑出来的值大。这意味着答案取出了比拓扑序某个时候,入度为0的点的最大值还大的数,这显然是不可能的。所以不存在更有的答案,所以这个答案就是最优的答案。

Code

  1 /**
  2  * poj
  3  * Problem#3687
  4  * Accepted
  5  * Time:32ms
  6  * Memory:1116k
  7  */
  8 #include <iostream>
  9 #include <cstdio>
 10 #include <ctime>
 11 #include <cmath>
 12 #include <cctype>
 13 #include <cstring>
 14 #include <cstdlib>
 15 #include <fstream>
 16 #include <sstream>
 17 #include <algorithm>
 18 #include <map>
 19 #include <set>
 20 #include <stack>
 21 #include <queue>
 22 #include <vector>
 23 #include <stack>
 24 #ifndef WIN32
 25 #define Auto "%lld"
 26 #else
 27 #define Auto "%I64d"
 28 #endif
 29 using namespace std;
 30 typedef bool boolean;
 31 const signed int inf = (signed)((1u << 31) - 1);
 32 const double eps = 1e-6;
 33 const int binary_limit = 128;
 34 #define smin(a, b) a = min(a, b)
 35 #define smax(a, b) a = max(a, b)
 36 #define max3(a, b, c) max(a, max(b, c))
 37 #define min3(a, b, c) min(a, min(b, c))
 38 template<typename T>
 39 inline boolean readInteger(T& u){
 40     char x;
 41     int aFlag = 1;
 42     while(!isdigit((x = getchar())) && x != '-' && x != -1);
 43     if(x == -1) {
 44         ungetc(x, stdin);    
 45         return false;
 46     }
 47     if(x == '-'){
 48         x = getchar();
 49         aFlag = -1;
 50     }
 51     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
 52     ungetc(x, stdin);
 53     u *= aFlag;
 54     return true;
 55 }
 56 
 57 ///map template starts
 58 typedef class Edge{
 59     public:
 60         int end;
 61         int next;
 62         Edge(const int end = 0, const int next = -1):end(end), next(next){}
 63 }Edge;
 64 
 65 typedef class MapManager{
 66     public:
 67         int ce;
 68         int *h;
 69         vector<Edge> edge;
 70         MapManager(){}
 71         MapManager(int points):ce(0){
 72             h = new int[(const int)(points + 1)];
 73             memset(h, -1, sizeof(int) * (points + 1));
 74         }
 75         inline void addEdge(int from, int end){
 76             edge.push_back(Edge(end, h[from]));
 77             h[from] = ce++;
 78         }
 79         inline void addDoubleEdge(int from, int end){
 80             addEdge(from, end);
 81             addEdge(end, from);
 82         }
 83         Edge& operator [] (int pos) {
 84             return edge[pos];
 85         }
 86         inline void clear() {
 87             edge.clear();
 88             delete[] h;
 89         }
 90 }MapManager;
 91 #define m_begin(g, i) (g).h[(i)]
 92 #define m_endpos -1
 93 ///map template ends
 94 
 95 int n, m;
 96 MapManager g;
 97 int* dag;
 98 int* dep;
 99 
100 inline boolean init() {
101     if(!readInteger(n))    return false;
102     readInteger(m);
103     g = MapManager(n);
104     dag = new int[(n + 1)];
105     dep = new int[(n + 1)];
106     memset(dag, 0, sizeof(int) * (n + 1));
107     for(int i = 1, a, b; i <= m; i++) {
108         readInteger(a);
109         readInteger(b);
110         g.addEdge(b, a);
111         dag[a]++;
112     }
113     return true;
114 }
115 
116 priority_queue<int> que;
117 inline void topu() {
118     for(int i = 1; i <= n; i++)
119         if(!dag[i]) {
120             que.push(i);
121         }
122     int cnt = 0;
123     while(!que.empty()) {
124         int e = que.top();
125         dep[e] = cnt++;
126         que.pop();
127         for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) {
128             int& eu = g[i].end;
129             dag[eu]--;
130             if(!dag[eu])
131                 que.push(eu);
132         }
133     }
134 }
135 
136 inline void solve() {
137     topu();
138     for(int i = 1; i <= n; i++) {
139         if(dag[i]) {
140             puts("-1");
141             return;
142         }
143     }
144     for(int i = 1; i <= n; i++)
145         printf("%d ", n - dep[i]);
146     putchar('\n');
147 }
148 
149 inline void clear() {
150     g.clear();
151     delete[] dep;
152     delete[] dag;
153 }
154 
155 int T;
156 int main() {
157     readInteger(T);
158     while(T--) {
159         init();
160         solve();
161         clear();
162     }
163     return 0;
164 }
posted @ 2017-07-15 22:52  阿波罗2003  阅读(286)  评论(0编辑  收藏  举报