POJ-3687 Labeling Balls(拓撲)
阿新 • • 發佈:2018-06-07
efi pan name lose als spa 分享圖片 set printf
不一樣的拓撲排序
給定一些標記為1到n的數, 求出滿足a < b 的序列, 如果有多個輸出, 按先標簽1往前的位置, 然後按標簽2往前的位置, 對於每個標簽, 位置都盡量往前。
因為位置要往前,就不能正向建圖, 因為正向的拓撲每次在最前的都是最小的點, 並不能保證標簽1也在最前面, 比如
1 5 3 4 2
和
1 4 5 3 2
如果按拓撲排序, 答案一定是1 4 5 3 2, 因為4比5小, 但是題目想要各個標簽的位置往前, 這樣1, 2標簽位置一樣, 對於3標簽, 第一個在3處, 第二個在4處, 所以答案應該是上面那個。
所以正向建圖是標簽盡量往前,所以就反向建圖得到
2 4 3 5 1
和
2 3 5 4 1
用less 的優先隊列, 這樣每次都把最大的放在後面, 就把小的留在前面了, 對於每一個標簽, 都盡可能往後扔,最後在倒敘輸出, 就可以得到答案。
題目還有一個點, 要求輸出不是排序以後的各個標簽的順序, 而是在從1-n位置上的標簽。
所以在倒敘的時候需要 ans[t] = num–;
#include<map> #include<queue> #include<string> #include<vector> #include<math.h> #include<ctype.h> #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #define inf 0x3f3f3f3f typedef long long int ll; using namespaceView Codestd; const int maxn = 205; int n, m; int ans[maxn]; int ind[maxn]; bool maps[maxn][maxn]; void init() { memset(ans, 0, sizeof ans); memset(ind, 0, sizeof ind); memset(maps, 0, sizeof maps); } bool topu() { int num = n; priority_queue<int, vector<int>, less<int> > pq;for(int i=1; i<=n; i++) { if(ind[i] == 0) { pq.push(i); } } while(!pq.empty()) { int t = pq.top(); pq.pop(); ans[t] = num--; for(int i=1; i<=n; i++) { if(maps[t][i] == true) { ind[i]--; if(ind[i] == 0) pq.push(i); } } } if(num == 0) return true; else return false; } int main() { int T; scanf("%d", &T); while(T--) { init(); scanf("%d%d", &n, &m); for(int i=0; i<m; i++) { int u, v; scanf("%d%d", &u, &v); if(!maps[v][u]) { maps[v][u] = true; ind[u] ++; } } bool bo = topu(); if(bo) { for(int i=1; i<=n; i++) { printf("%d%c", ans[i], i==n ? ‘\n‘ : ‘ ‘); } } else { printf("-1\n"); } } return 0; }
POJ-3687 Labeling Balls(拓撲)