题目描述
题目来源:2017蓝桥杯国赛
小明的实验室有 N台电脑,编号 1⋯N。原本这 N 台电脑之间有 N-1条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。
不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了 BUG。
为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?
输入描述
输入范围:
第一行包含一个整数 N 。
以下 NN 行每行两个整数 a,b,表示 a 和 b 之间有一条数据链接相连。
其中, 1≤ N ≤10^5,1≤a,b≤N。
输入保证合法。
输出描述
按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。
输入输出样例
示例
输入
5
1 2
3 1
2 4
2 5
5 3
输出
1 2 3 5
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
思路:
1. 本题的意思是从给出的图(图中有环)中找出在环中的结点,并输出;
2. 首先用邻接表来存储给定的图(本题中使用元素为set类型的vector来实现),不可以用二维数组或者邻接矩阵来存储边,会超时的;
3. 如果一个点在环中,那么这个点的度一定大于等于2,如果一个点的度为1,那么这个点肯定在环外;
4. 删除度为1的点和其所连接的边(因为不在环内的点不是我们想要的),重复这个动作直到没有度为1的点;那么剩余的点(度大于等于2)便是环内的点;
//2017g 发现环
#include <iostream> vxgzh:xtsn
using namespace std;
#include <deque>
#include <vector>
#include <set>
#define N 100005
//邻接矩阵的应用(用别的会超时),
//从度为1的点开始,度为1不可能在环内;不断删除度为1的点和所连接的边;知道最后只存在度大于等于1的点,即环内的点
deque<int> dq; //临时存储 度为1的点
vector<int> ans; //保存最终答案
int main()
{
int n,i,a,b;
cin>>n;
set <int> s;
vector < set<int> > v(n+1); //邻接表的数据结构,每个点的邻接点用集合表示
for(i=0;i<n;i++) //输入
{
cin>>a>>b;
v[a].insert(b);v[b].insert(a); //保存到邻接矩阵中去
}
for(i=1;i<=n;i++)
{
if(v[i].size()==1) //邻接矩阵中每个点连接的元素个数 即为度
{
int index=*v[i].begin(); //取出唯一的邻接点
v[i].erase(index); v[index].erase(i); //删掉边(i,index) ,也可理解为给i和index降度
if(v[index].size()==1)
dq.push_back(index);
}
}
while(!dq.empty()) //没有度为1的点时循环结束
{
i=dq.front();dq.pop_front();
int index=*v[i].begin();
v[i].erase(index); v[index].erase(i);
if(v[index].size()==1)
dq.push_back(index);
}
for(i=1;i<=n;i++)
if(v[i].size()>=2) //输出度数大于等于2的点
ans.push_back(i);
for(i=0;i<ans.size()-1;i++) //输出结果
cout<<ans[i]<<" ";
cout<<ans[i]<<endl;
return 0;
}