1. 程式人生 > >POJ-3687 Labeling Balls(拓撲)

POJ-3687 Labeling Balls(拓撲)

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 namespace
std; 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; }
View Code

POJ-3687 Labeling Balls(拓撲)