2017.发现环(并查集水题)
blog最近没有更新因为在做并查集专题,按专题写题解,然后又要打省赛,(省三水过,题解还没时间写,现在又要准备蓝桥国赛)
- 并查集模板,但是我死磕路径压缩时进行保存答案
- 应该邻接表存图,然后在根节点不相同的地方,去dfs找成环的路上的点,
- 回溯是最重要的,能够回溯说明没有找到,需要取消标记然后pop路上的点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #include <iostream> #include <string.h> #include <vector> #include <algorithm>
using namespace std;
const int maxn = 1e5+10; int n; int pre[maxn]; vector<int> e[maxn]; vector<int> ans; bool vis[maxn];
void init() { for (int i=1; i<maxn; i++) pre[i] = i; } int find(int x) { if (x == pre[x]) return x; return pre[x] = find(pre[x]); } bool flag = 1; void dfs(int cur,int endn) { if (cur == endn) { sort(ans.begin(),ans.end() ); for (int i=0; i<ans.size(); i++) { printf("%d",ans[i]); if (i != ans.size()-1) printf(" "); flag = false; } } for (int i=0; i<e[cur].size(); i++) { int to = e[cur][i]; if (!vis[to] && flag) { vis[to] = 1; ans.push_back(to); dfs(to,endn); vis[to] = 0; ans.pop_back(); } } } int main() {
cin >> n; int start,endn; init(); for (int i=1; i<=n; i++) { int a,b; cin >> a >> b;
e[a].push_back(b); e[b].push_back(a);
int ra = find(a); int rb = find(b); if (ra != rb) { pre[ra] = rb; } else { start = a; endn = b; } } vis[start] = 1; ans.push_back(start); dfs(start , endn); return 0; }
|