思路:用set保存有哪些编号。用并查集判断①是否有环 ②是否只有一棵树
输入a,b就把a,b合并,如果a,b已经在一个集合中还要合并a,b那么就形成了环就是No,最后扫一边这些编号看形成了几棵树(即有几个根节点),超过一个就NO。
数据有个很坑的点是输入0 0,应该输出Yes。程序最后多附了两组数据,有需要的可以看一下。
//#include<bits/stdc++.h>
#include<cstdio>
#include<iostream>
#include<set>
using namespace std;
const int MAXN = 100005;
int f[MAXN];
set<int> s;//所有的编号
bool flag;//Yes/No
void init()
{
s.clear();
flag = true;
for (int i = 0; i < MAXN; i++) f[i] = i;
}
int find(int x)
{
if (f[x] == x) return x;
f[x] = find(f[x]);
return f[x];
}
void Union(int a, int b)
{
int root1 = find(a), root2 = find(b);
if (root1 != root2) f[root1] = root2;
else flag = false;
}
int main()
{
init();
int a, b;
while (~scanf("%d%d", &a, &b) && !(a == -1 && b == -1))
{
if (a == 0 && b == 0)
{
int cnt = 0;
for (auto i: s)
{
if (f[i] == i) cnt++;
if (cnt >= 2) { flag = false; break; }
}
if (flag) printf("Yes\n");
else printf("No\n");
init();
}
else
{
s.insert(a); s.insert(b);
Union(a, b);
}
}
return 0;
}
/*
6 8 5 3 5 2 6 4
5 6 0 0
8 1 7 3 6 2 8 9 7 5
7 4 7 8 7 6 0 0
3 8 6 8 6 4
5 3 5 6 5 2 0 0
1 2 3 4 3 5 4 5 0 0
0 0
-1 -1
*/