hdu 4857 反向拓撲模板題,入門
阿新 • • 發佈:2018-11-13
之前寫過的部落格,今天回頭看時,發現格式好亂,重新寫一下。
---------------------------------------
分析
首先先處理特殊關係,對於有要求的數字,在他們倆之間建立一條邊,a->b 同時b的入度++,表示b的限制條件增加1.那麼在處理時,用一個優先佇列按照greater的順序push,(push入度為0)那麼這道題就得到解決了,然後在這道題中是行不通的,因為對於這樣一組資料3 1一共有5個點的情況下,那麼按照上面的方法那麼就會輸出2 3 1,然而這並不符合題意因為題目中要求是1要儘可能上前,因該輸出的是3 1 2,那麼該如何處理這個問題喃?首先應該分析為什麼會出現這個問題,是因為在優先佇列《greater》下因為2的入度為0,所以會先入隊,那麼應該怎麼讓3先入隊?大家都是入隊為0,並且老子還抱著個大腿啊喂!於是就考慮到反向拓撲,然後當然也要反向建圖是不是。優先佇列也要按照less的順序排序,這樣做的結果是5 4 2 1 3然後再反向輸出就GG了,不要忘記重邊的判斷哦。
程式碼
#include<cstdio> #include<cstdlib> #include<iostream> #include<set> #include<stack> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn = 3e4+10; int in[maxn]; int n, m; stack<int>iron; vector<int>vec[maxn]; typedef pair<int, int>pii; void ini() { memset(in, 0, sizeof(in)); for (int i = 0; i <= n; i++) vec[i].clear(); while (!iron.empty()) iron.pop(); } void solve() { priority_queue <int, vector<int> >que; for (int i = 1; i <= n; i++) { if (in[i] == 0) que.push(i); } while (!que.empty()) { int t = que.top(); iron.push(t); que.pop(); for (int i = 0; i < vec[t].size(); i++) { int p = vec[t][i]; if (--in[p] == 0) que.push(p); } } } void show() { while (iron.size() > 1) { printf("%d ", iron.top()); iron.pop(); } printf("%d\n", iron.top()); } int main() { int t; scanf("%d", &t); while (t--) { scanf("%d %d", &n, &m); ini(); set<pii>s; for (int i = 0; i < m; i++) { int a, b; scanf("%d %d", &a, &b); pii p = make_pair(b, a); if (s.count(p) == 0) { s.insert(p); vec[b].push_back(a); in[a]++; } } solve(); show(); } // system("pause"); return 0; }