標題:發現環
小明的實驗室有N台電腦,編號1~N。原本這N台電腦之間有N-1條數據鏈接相連,恰好構成一個樹形網絡。在樹形網絡上,任意兩台電腦之間有唯一的路徑相連。
不過在最近一次維護網絡時,管理員誤操作使得某兩台電腦之間增加了一條數據鏈接,於是網絡中出現了環路。環路上的電腦由於兩兩之間不再是只有一條路徑,使得這些電腦上的數據傳輸出現了BUG。
為了恢復正常傳輸。小明需要找到所有在環路上的電腦,你能幫助他嗎?
輸入
第一行包含一個整數N。
以下N行每行兩個整數a和b,表示a和b之間有一條數據鏈接相連。
對於30%的數據,1 <= N <= 1000
對於100%的數據, 1 <= N <= 100000, 1 <= a, b <= N
輸入保證合法。
輸出
按從小到大的順序輸出在環路上的電腦的編號,中間由一個空格分隔。
樣例輸入:
5
1 2
3 1
2 4
2 5
5 3
樣例輸出:
1 2 3 5
資源約定:
峰值內存消耗 < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。
注意: main函數需要返回0
注意: 只使用ANSI C/ANSI C++ 標准,不要調用依賴於編譯環境或操作系統的特殊函數。
注意: 所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。
提交時,注意選擇所期望的編譯器類型。
思路
在輸入邊的同時,利用並查集判斷當前兩點是否已經連通,如果已經連通,那么這兩點一定在環上,並且這條邊也是環上的。那么以這兩點分別作為起點和終點,用DFS找到起點到終點的路徑,這條路徑上的所有點就是環上的所有點!
AC代碼
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 100000+5; 7 int par[maxn], vis[maxn], ret[maxn]; 8 vector<int> edge[maxn]; 9 int n, s, f; 10 11 int findRoot(int x) { 12 return par[x] == x ? x : par[x] = findRoot(par[x]); 13 } 14 15 void dfs(int u, int ind) { 16 ret[ind] = u; 17 if(u == f) { 18 sort(ret, ret + ind + 1); 19 for(int i = 0; i <= ind; i++) { 20 printf("%d%c", ret[i], i==ind?'\n':' '); 21 } 22 return; 23 } 24 vis[u] = 1; 25 for(int i = 0; i < edge[u].size(); i++) { 26 int v = edge[u][i]; 27 if(!vis[v]) dfs(v, ind+1); 28 } 29 vis[u] = 0; 30 } 31 32 int main() { 33 while(scanf("%d", &n) == 1) { 34 int u, v; 35 for(int i = 1; i <= n; i++) par[i] = i; 36 for(int i = 0; i < n; i++) { 37 scanf("%d%d", &u, &v); 38 int ru = findRoot(u), rv = findRoot(v); 39 if(ru == rv) s = u, f = v; 40 else { 41 par[ru] = rv; 42 edge[u].push_back(v); 43 edge[v].push_back(u); 44 } 45 } 46 memset(vis, 0, sizeof(vis)); 47 dfs(s, 0); 48 } 49 return 0; 50 }
如有不當之處歡迎指出!