首页 > 技术文章 > [蓝桥杯]:发现环 -- 并查集、DFS

prjruckyone 2020-04-10 10:45 原文

题目:

样例:

考察点:

并查集判断是否有环,DFS寻找从环的起点到终点的路径。

图解:

Code:

#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 1e5 + 10;

int vis[maxn],fa[maxn];

vector<int>G[maxn],ve;

int n,pos = 0,l,r;

void init() {
	for(int i = 1; i <= n; i ++) {
		fa[i] = i;
	}
	return ;
}

int get(int x) {
	return x == fa[x] ? x : fa[x] = get(fa[x]);
}

void Union(int x,int y) {
	int xx = get(x);
	int yy = get(y);
	if(xx == yy) return ;
	fa[yy] = xx;
	return ;
}

// 标记是否已经找到合适的路径 
bool flag = true;

void DFS(int l,int r) {
	if(l == r) {
		sort(ve.begin(),ve.end());
		for(int i = 0; i < ve.size(); i ++) {
			cout << ve[i];
			// 注意行末空格 
			if(i != ve.size() - 1) cout << " ";
		}
		flag = false;
		return ;
	}
	for(int i = 0; i < G[l].size(); i ++) {
		int y = G[l][i];
		if(vis[y] == 0 && flag) {
			ve.push_back(y);
			vis[y] = 1;
			DFS(y,r);
			// 还原现场(回溯),此路径有可能不是我们所要的最终路径 
			ve.pop_back();                          
			vis[y] = 0;
		}
	}
	return ;
}

int main(void) {
	scanf("%d",&n);
	int u,v;
	init();
	for(int i = 1; i <= n; i ++) {
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
		// 并查集寻找环,找到路径的起点和终点 
		if(get(u) != get(v)) Union(u,v);
		else {
			l = u,r = v;
		}
	}
	// 将起点入队并且标记 
	ve.push_back(l);
	vis[l] = 1;
	DFS(l,r);
	return 0;
}

推荐阅读