历届试题 发现环
时间限制:1.0s 内存限制:256.0MB
问题描述
小明的实验室有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
①:一开始用dfs+并查集,如果读入已有元首的两个元素&&这两个元素元首相同,那么这个元素在环上,然后dfs(要回溯)一下就可以了。数据范围可能卡掉几组数据,但是奇迹过了。。。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
#define MAXN 100005
int pre[MAXN],e,n,ro,s,jd=0;
int path[MAXN];
bool vis[MAXN],r[MAXN];
vector<int>v[100005];
vector<int>::iterator it;
int found(int x){/*找元首*/
int r=x;
while(pre[r]!=r){
r=pre[r];
}
int i=x,j;
while(i!=r){
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y){/*x y合并*/
int fx = found (x),fy=found(y);
if(fx!=fy){
pre[fx]=fy;
}
}
void dfs(int pos,int step){
if(pos==e){
ro=step-1;
jd=1;
return ;
}
for(int i=0;i<(int)v[pos].size();i++){
if(jd){break;}
int to=v[pos][i];
if(!vis[to]){
vis[to]=1;
path[step]=to;
dfs(to,step+1);
vis[to]=0;
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
if(pre[x]==pre[y]&&vis[x]&&vis[y]){
e=y;
s=x;
}
vis[x]=1;vis[y]=1;
join(x,y);
}
memset(vis,0,sizeof(vis));
path[0]=s;
dfs(s,1);
for(int i=0;i<=ro;i++){
r[path[i]]=1;
}
for(int i=1;i<=100001;i++)
if(r[i]) printf("%d ",i);
return 0;
}
②正确解法:拓扑排序。
排序的时候每次取的是只有一条边的顶点,然后剩下的点就是结果。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
#define MAXN 100005
int n;
int in[MAXN];
bool vis[MAXN];
vector<int>v[100005];
vector<int>::iterator it;
void TopSort(){
queue<int>q;
for(int i=1;i<=n;i++){
if(in[i]==1){
vis[i]=1;
q.push(i);
}
}
while(!q.empty()){
int p=q.front();q.pop();
for(int i=0;i<(int)v[p].size();i++){
int x=v[p][i];
in[x]--;
if(in[x]==1){
q.push(x);
vis[x]=1;
}
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
in[x]++;in[y]++;
}
TopSort();
for(int i=1;i<=n;i++)
if(!vis[i]) printf("%d ",i);
return 0;
}
Topsort模板:
bool topo(){
queue<int>Q;
int sum=0;
for(int i=1;i<=n;i++){
if(in[i]==0)
Q.push(i);
}
while(!Q.empty()){
int u=Q.front();
Q.pop();
sum++;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
--in[v];
if(in[v]==0)
Q.push(v);
}
}
return sum==n;
}