2017蓝桥杯决赛-发现环 数据结构|搜索

问题描述
  小明的实验室有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


分析: 可以利用一个栈 任意取一个点开始搜索 然后把所有没入栈的元素入栈 只要没有重复元素入栈 就一直搜索下去 由于本来就是一棵树 并且只有一个环 所以当我们遇到重复入栈的元素的时候 就不断弹出 知道把问题元素弹完为止 那么就相当于把这个环中的所有元素都弹出来了


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
stack<int>S;
priority_queue<int,vector<int>,greater<int> >pq;
vector<int>g[maxn];
bool fin,bok[maxn];
void dfs(int x,int f){
	if(!bok[x]){
		bok[x] = 1;S.push(x);
		for(int i=0;i<g[x].size();i++){
			int t = g[x][i];
			if(t!=f)dfs(t,x);
			if(fin)return;	
		}
		if(S.top()==x){
			S.pop();
		}
	}else{
		while(1){
			int t ;
			if(!S.empty()){
				t  = S.top();S.pop();
				pq.push(t);
				bok[t] = false;
				if(t==x)break;
			}
		}
		if(pq.size()>1){
			fin=1;return;
		}
	}
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int s,e;
		scanf("%d%d",&s,&e);
		g[s].push_back(e);
		g[e].push_back(s);
	}
	dfs(1,-1);
	while(!pq.empty()){
		int t = pq.top();pq.pop();
		if(pq.size()==0)printf("%d\n",t);
		else printf("%d ",t);
	} 
	return 0;
} 


拓扑排序也可以做

#include<bits/stdc++.h>
#include<set>
using namespace std;
set<int>g[1000010];
bool del[1000010];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int s,e;
		scanf("%d%d",&s,&e);
		g[s].insert(e);
		g[e].insert(s);		
	}		
	int cnt=0;
	queue<int>que;
	for(int i=1;i<=n;i++){
		if(g[i].size()==1)que.push(i);	
	}
	while(!que.empty())
	{
		int t = que.front();
		que.pop();
		for(set<int>::iterator i=g[t].begin();i!=g[t].end();i++){
			int now = *i;
			g[now].erase(t);
			if(g[now].size()==1){
				que.push(now);
				cnt++;
			}
		}
		g[t].clear(); 
	}
	
	for(int i=1;i<=n;i++){
		if(g[i].size())
		{
			cnt--;
			if(cnt==0)printf("%d\n",i);
			else printf("%d ",i);
		}	
	}

	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_33859479/article/details/80411372