此题是一个思想简单, 实现困难的题,因为有很多的小情况
1. 首先--判断集合是否有环--用并查集 ---> 新加入一条边的时候
if( find(a) != find(b) )//判断结果2
Union(a, b);
else //若果在未加入时, 发现发现已加入的点与未加入的点同根, 则说明图中有环
{
init();
printf("No\n");
while( scanf("%d%d", &a, &b) && a+b){ }
continue;
}
2. 如果直到 0 0, 碰到一组数据结束, 不能说明符合条件!!!
不能说明符合条件!!!
不能说明符合条件!!!
重要的事情说三遍, 不符合是因为,如果之前输入的数据, 组成了若干个不相连的集合, 那么之前的同根判断会做出错误的判断
所以要判断图的连通性,代码如下:
void only_one_gater()
{
int cnt = 0;
for(int i = 1; i <= temp; ++i)
{
if(pre[i] == i && vis[i] == true)//若果vis标记到,某个点曾经出现过, 而且这个点位根节点,则cnt++
{
cnt++;
}
if(cnt > 1) 说明有好几个不连通的集合
{
printf("No\n");
return;
}
}
printf("Yes\n");
}
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 100100
using namespace std;
int a, b, temp;
int pre[maxn];
bool vis[maxn];
void init()
{
for(int i = 0; i < maxn; ++i)
pre[i] = i;
fill(vis, vis+maxn, false);
temp = -1;
}
int find(int& index)
{
return pre[index] = pre[index] == index?index: find(pre[index]);
}
void Union(int& a, int& b)
{
pre[find(a)] = find(b);
}
void only_one_gater()
{
int cnt = 0;
for(int i = 1; i <= temp; ++i)
{
if(pre[i] == i && vis[i] == true)
{
cnt++;
}
if(cnt > 1)
{
printf("No\n");
return;
}
}
printf("Yes\n");
}
int main()
{
init();
while( ~scanf("%d%d", &a, &b) )
{
vis[a] = vis[b] = true;
temp = max(a,max(b,temp));
if(a+b == 0) //一组结束,得出结果1
{
only_one_gater();
init();
continue;
}
if(a + b == -2) //全部结束
return 0;
if( find(a) != find(b) ) //判断结果2
Union(a, b);
else
{
init();
printf("No\n");
while( scanf("%d%d", &a, &b) && a+b){ }
continue;
}
}
return 0;
}