题目描述:
http://acm.hdu.edu.cn/showproblem.php?pid=3635
思路:
这道题等价于,判断所给图是否连通,是否是棵树。
判断是否连通:
已知一棵树的节点个数 = 边的条数 + 1,
若不能满足这个条件,则说明所给数据构成了不止一棵树,即所给图不连通。
判断是否是棵树:
若待合并的两个节点在同一个集合中,则二者相连会构成回路,就不是树了。
代码:
//测试数据:
//1 2 1 2 0 0
//1 2 2 1 0 0
//1 1 0 0
//0 0
//1 2 3 4 0 0
//
//No
//No
//No
//Yes
//No
#include<bits/stdc++.h>
using namespace std;
#define MAX 100001
int room[MAX];
int cnt[MAX];//连通的房间个数
int points,edges;//节点个数、边条数
bool fit;//是否符合小希的思路
//初始化
void init(){
points = 1;
edges = 0;
fit = true;
for(int i=1;i<MAX;i++){
room[i] = i;
cnt[i] = 1;
}
}
//寻找节点 x 所在的房间集和
int find(int x){
if(x == room[x]){
return x;
}
int root = find(room[x]);
room[x] = root;
return root;
}
//合并
void union_set(int x, int y){
x = find(x);
y = find(y);
//若 x 和 y 在同一个集合中,则二者相连会构成回路
if(x == y){
fit = false;
return;
}
//优化
if(cnt[x] <= cnt[y]){
room[x] = y;
cnt[y] += cnt[x];
points = (points > cnt[y])?points:cnt[y];
}
else{
room[y] = x;
cnt[x] += cnt[y];
points = (points > cnt[x])?points:cnt[x];
}
//边的条数加一
edges++;
}
int main(){
int x,y;
init();
while(scanf("%d %d", &x, &y) && (x != -1 || y != -1)){
if(x == 0 && y == 0){
//这道题等价于,判断所给图是否连通,是否是棵树
//已知,一棵树的节点个数 = 边的条数 + 1
//若不满足这个条件,则说明存在着不止一棵树,即所给图不连通
if(points != (edges+1)){
fit = false;
}
if(fit){
printf("Yes
");
}
else{
printf("No
");
}
//记得初始化
init();
continue;
}
union_set(x, y);
}
}