题意
给出一个图,问这个图是否是一棵树
思路
首先判断这个图有没有环,这个直接用并查集就可以判断,为此我改进了并查集的模板,然后就是判断这个图是不是一片森林,这个需要记录下有多少个点,如果有n个点,有n-1条边就是一棵树
传送门
http://acm.hdu.edu.cn/showproblem.php?pid=1272
Code
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
class UnionFind {
private:
int * fa;
int size;
public:
UnionFind(int n) {
size = n;
fa = new int[n+1];
Init();
}
~UnionFind() {
delete[] fa;
}
void Init() {
for(int i = 1 ; i <= size ; i ++) {
fa[i] = i;
}
}
int Find(int x) {
if(fa[x] != x) {
fa[x] = Find(fa[x]);
}
return fa[x];
}
bool Union(int x,int y) {
int fx = Find(x);
int fy = Find(y);
if(fx != fy) {
fa[fx] = fy;
return true;
}
else {
return false;
}
}
int GetCount() {
int count = 0;
for(int i = 1 ; i <= size ; i ++) {
if(fa[i] == i) {
count ++;
}
}
return count;
}
};
const int maxn = 100000;
bool vis[maxn+1];
int main() {
int u,v;
bool ret;
UnionFind uf(maxn);
while(scanf("%d %d",&u,&v)) {
if(u == -1 && v == -1) {
break;
}
if(u == 0 && v == 0) {
puts("Yes");
continue;
}
memset(vis,0,sizeof(vis));
ret = true;
int cnt = 0;
uf.Init();
uf.Union(u,v);
vis[u] = true; vis[v] = true;
while(scanf("%d %d",&u,&v)) {
if(u == 0 && v == 0) {
break;
}
vis[u] = true; vis[v] = true;
if(false == uf.Union(u,v)) {
ret = false;
}
}
for(int i = 1 ; i <= maxn ; i++) {
if(vis[i]) {
cnt ++;
}
}
if(true == ret && uf.GetCount() + cnt - 1 == maxn) {
puts("Yes");
}
else {
puts("No");
}
}
return 0;
}