0发现环 - 蓝桥云课
找到环
不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了BUG。
为了恢复正常传输,小明需要找到所有在环路上的电脑,你能帮助他吗?
输入描述
输入范围:
- 第一行包含一个整数 N。
- 以下 N 行每行两个整数 a,b,表示 a 和 b 之间有一条数据链接相连。
- 其中,1≤N≤105,1≤a,b≤N。
- 输入保证合法。
输出描述
按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。
输入输出样例
示例:
输入:
5
1 2
3 1
2 4
2 5
5 3
输出:
1 2 3 5
运行限制
- 最大运行时间:1s
- 最大运行内存:256M
总通过次数:3106 | 总提交次数:3881 | 通过率:80%
难度:困难 标签:2017,拓扑排序,并查集,国赛,DFS
思路:
图中只有一个环。
因为环的度一定>=2,所以我们可以用拓扑排序维护度为1的节点。剩下的节点>=2就是环的节点
代码如下:
#include <iostream>
#include <queue>
#include<algorithm>
using namespace std;
const int N = 1e5+10;
int n,tot;
int du[N];
struct Edge{
int to,next;
}e[4*N];
int head[N];
void add(int u,int v)
{
++tot;
e[tot].next = head[u];
e[tot].to = v;
head[u] = tot;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
queue <int> r;
cin >> n;
for(int i = 1 ; i <= n ; i++)
head[i] = -1;
for(int i = 1 ; i <= n ; i++)
{
int u,v;
cin >> u >> v;
add(u,v);
add(v,u);
du[u]++;
du[v]++;
}
for(int i = 1 ; i <= n ; i++)
{
if(du[i] == 1)
{
r.push(i);
}
}
while(!r.empty())
{
int pos = r.front();
du[pos]--;
r.pop();
int u = head[pos];
while(u != -1)
{
int to = e[u].to;
if(du[to] > 0)
{
du[to]--;
if(du[to] == 1)
{
r.push(to);
}
}
u = e[u].next;
}
}
for(int i = 1 ; i <= n ; i++)
{
if(du[i] > 1)
cout << i << " ";
}
return 0;
}
