1. 程式人生 > >逃生(HDU4857 + 反向拓撲排序)

逃生(HDU4857 + 反向拓撲排序)

emp 反向 .cn back HP 隊列 ring IT ()

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4857

題面是中文題面,就不解釋題意了,自己點擊鏈接去看下啦~這題排序有兩個條件,一個是按給定的那個序列(即輸入的u,v,優先級最高),一個是序號從小到大(優先級次之)。正向的話由於這兩個條件不好維護,所以就想著用反向拓撲排序來實現。首先記錄每個節點的出度,然後用優先隊列來維護順序(使用默認的從大到小排序),最後反向輸出即可。

代碼實現如下:

 1 #include <queue>
 2 #include <cstdio>
 3 #include <vector>
 4
#include <cstring> 5 using namespace std; 6 7 const int maxn = 3e4 + 7; 8 int t, n, m, u, v, rk; 9 int InDeg[maxn], Rank[maxn]; 10 vector<int> G[maxn]; 11 12 void topsort() { 13 priority_queue<int> q; 14 for(int i = 1; i <= n; i++) { 15 if(InDeg[i] == 0
) q.push(i); 16 } 17 int x; 18 while(!q.empty()) { 19 x = q.top(), q.pop(); 20 Rank[rk++] = x; 21 int t = G[x].size(); 22 for(int i = 0; i < t; i++) { 23 if(--InDeg[G[x][i]] == 0) q.push(G[x][i]); 24 } 25 } 26 } 27 28 int
main() { 29 scanf("%d", &t); 30 while(t--) { 31 scanf("%d%d", &n, &m); 32 for(int i = 0; i <= n; i++) { 33 G[i].clear(); 34 } 35 memset(InDeg, 0, sizeof(InDeg)); 36 for(int i = 0; i < m; i++) { 37 scanf("%d%d", &u, &v); 38 G[v].push_back(u); 39 InDeg[u]++; 40 } 41 rk = 0; 42 topsort(); 43 for(int i = n - 1; i >= 0; i--) { 44 if(i != (n - 1)) { 45 printf(" "); 46 } 47 printf("%d", Rank[i]); 48 } 49 printf("\n"); 50 } 51 return 0; 52 }

逃生(HDU4857 + 反向拓撲排序)