问题描述
小明的实验室有N台电脑,编号1~N。原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。
不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了BUG。
为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?
不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了BUG。
为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?
输入格式
第一行包含一个整数N。
以下N行每行两个整数a和b,表示a和b之间有一条数据链接相连。
对于30%的数据,1 <= N <= 1000
对于100%的数据, 1 <= N <= 100000, 1 <= a, b <= 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 1
2 4
2 5
5 3
样例输出
1 2 3 5
题目思路
首先我写的代码应该是有问题的,可能连数据都没输入完答案就出来了,但确实是AC了(大概数据里都是最后一条边输入才会生成环),代码先放这里,下次优化
基本思路:先并查集判断当一条边的两个顶点的祖先一样,说明这两个点是环的一部分,从一个点出发dfs到另一个顶点即可
还有一个思路是在网上看的:拓扑排序每次删掉度为1的点,一直删一直删,剩下的就是环了
AC代码
#include<iostream> #include<stack> #include<vector> #include<algorithm> #include<cstdio> using namespace std; const int maxn = 100010; int per[maxn]; int n; vector<int> e[maxn]; stack<int>res; int vis[maxn]; int a[maxn]; int find(int x){ if (x == per[x]) return x; return per[x] = find(per[x]); } void join(int x, int y){ int fx = find(x), fy = find(y); if (fx != fy) per[fx] = fy; } void print(){ int t = 0; while (!res.empty()){ a[t++] = res.top(); res.pop(); } sort(a,a+t); for (int i = 0; i < t-1; i++){ cout << a[i] << ' '; } cout << a[t - 1] << endl; } void dfs(int start,int end){ res.push(start); vis[start] = 1; if (start == end){ print(); exit(0); } for (int i = 0; i < e[start].size(); i++){ if (e[e[start][i]].size() >= 2 && vis[e[start][i]] == 0) dfs(e[start][i], end); } res.pop(); vis[start] = 0; } int main() { int a, b; cin >> n; for (int i = 0; i <= n; i++){ per[i] = i; vis[i] = 0; } for (int i = 1; i <= n; i++){ scanf("%d%d",&a,&b); e[a].push_back(b); e[b].push_back(a); int fa = find(a), fb = find(b); if (fa != fb) per[fa] = fb; else dfs(a,b); } return 0; }
题解效率