题意:给一个图,判断这个图是不是存在环,还有判断这个图中的任意两个顶点是不是连通的。
分析:使用并查集判断这个图是不是存在环以及判断这个图中的任意两个顶点是不是连通的。
另外还有一个地方需要注意,这个图中的顶点是任意编号的,编号不是连续的,所以我们要用一个数组把顶点的编号标记一下。
关于并查集主要有两个操作,一是查询两个元素是不是在同一个集合中,二是合并两个集合。
这是查询的操作:
int find(int i)
{
return i == father[i] ? i : father[i] = find(father[i]);
}
这是合并两个集合的操作,并判断图中是否存在环。如果存在环返回false,否则返回true。
bool merge(int a,int b)
{
int x = 0, y =0;
x = find(a);
y = find(b);
if(x != y)
{
father[y] = x;
return true;
}
else
{
return false;
}
}
下面是代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
using namespace std;
const int A = 100000+10;
int father[A], array[A];
int M = 0, N = 0;
void inital()
{
for(int i =0; i < A; i++)
{
father[i] = i;
array[i] = 0;
}
}
int find(int i)
{
return i == father[i] ? i : father[i] = find(father[i]);
}
bool merge(int a,int b)
{
int x = 0, y =0;
x = find(a);
y = find(b);
if(x != y)
{
father[y] = x;
return true;
}
else
{
return false;
}
}
int main()
{
int count = 0;
bool tf;
while(scanf("%d %d",&M,&N) != EOF&&(M != -1 || N!= -1))
{
inital();
count = 1;
if(M == 0 && N == 0)
{
printf("Yes\n");
continue;
}
array[M] = 1;
array[N] = 1;
tf = merge(M,N);
if(tf == false)
{
count = 0;
}
while(scanf("%d %d",&M,&N) != EOF && (M||N))
{
array[M] = 1;
array[N] = 1;
tf = merge(M,N);
if(tf == false)
{
count = 0;
}
}
int ans = 0;
for(int i = 0; i < A; i++)
{
if(array[i])
{
if(i == father[i])
ans++;
}
}
if(ans == 1 && count == 1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}