題目大意
有一種排序是,給你一些英文字母,再告訴你某個英文字母必須要在另個英文字母前面(定義為記錄關係)。
請輸出一種排序可以符合題目的所有記錄關係。
題目連結
重點觀念
分析
這邊我用另種方式來寫拓樸排序,想說透過 DFS 的方式看能否寫出拓樸排序,但我認為我寫得不太好,這是我的自創方式,建議還是不要多看這個。
但如果想要了解我的思考,還是建議看看。
這題比較不好輸入,要用上 stringstream
這是類似於 cin
,透過這個可以方便輸入題目資料,再來記錄所有的記錄關係,每次進行 DFS 時,確認之前的 DFS 的資料都有符合記錄關係才繼續,如果沒有就退回上層 DFS。
缺點是每層 DFS 都要做一次確認,時間複雜度會爆炸多,建議在比賽中還是不要使用。
DFS 只要能夠成功就一定會是拓樸排序,因為每層都會確認關係,因此只要走到 DFS 深度與原本序列一樣長就可以。
參考連結
UVa872 - morris821028
心得
其實我一開始已經忘記拓樸排序了,那是高中學的,上了大學後都忘記了…,然後在根據 Competitive Programming3,複習的過程中在寫這題 UVA,翻著有沒有其他人寫詳解,結果發現 morris821028 沒有寫詳解QQ,但是有 github,就看著他的程式碼來解,但後來發現師大演算法的 BFS 版本更好,後面就改用師大演算法的了。
很感謝師大演算法與 morris821028 大大,願意讓學習資源在網路上才有辦法讓我學習到,很感謝他們。
題目程式碼
會在下面放一些簡單註解,供大家學習時參考。
- 紀錄關係
a,b ,則 a 必須在 b 前面、c,d,則 c 必須在 d 前面,此時我們會稱 a,c 為前面節點、b,d 是後面節點。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <iostream> #include <bits/stdc++.h> #define LOCAL #define MAXN 40 using namespace std; stringstream ss; int graph[MAXN], visit[MAXN];
int order[MAXN][MAXN]; int n, lg, flag2, flag3;
char ch; vector<int> ans;
void dfs(int x){ visit[x] = 1; ans.push_back(x);
if(ans.size() == lg){ flag2 = 0; cout << (char) (ans[0] + 'A'); for(int i = 1; i < ans.size(); i++) cout << ' ' << (char) (ans[i] + 'A'); cout << '\n'; return; }
int flag; for(int i = 0; i < MAXN; i++){ flag = 1; if(graph[i] != 1 || visit[i] == 1) continue; for(auto it: ans){ if(order[it][i]){ flag = 0; break; } }
if(flag == 1){ dfs(i); visit[i] = 0; ans.pop_back(); } } }
int main() { #ifdef LOCAL freopen("in1.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif cin >> n; cin.ignore(); flag3 = 1; while(n--){ string temp; getline(cin, temp); getline(cin, temp); ss.clear(); ss.str(""); ss << temp; memset(graph, 0, sizeof(graph)); memset(order, 0, sizeof(order)); lg = 0; while(ss >> ch){ graph[ch - 'A'] = 1; lg++; }
getline(cin, temp); ss.clear(); ss.str(""); ss << temp; while(ss >> temp) order[temp[2] - 'A'][temp[0] - 'A'] = 1;
flag2 = 1; if(flag3 == 0) cout << "\n"; if(flag3) flag3 = 0; for(int i = 0; i < MAXN; i++){ if(graph[i] == 1){ dfs(i); ans.pop_back(); visit[i] = 0; } } if(flag2) cout << "NO\n";
}
return 0; }
|