并查集 判断是否有环、未给出点数判断集合数是否大于1
就是判断是否是最小生成树吧
判断有环:
若输入两点的根相同则有环
判断所有点是否都在同一集合内:
此题有点不严谨吧,还是看了别人代码才知道,给的点是一个区间内的所有点。
合并过程中把出现的点都标记,把最小和最大的找到,枚举在该范围内的点,看有几个根,有几个根就有几个集合。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define ll __int64
using namespace std;
int r[100005],n,m,ans,vis[100005];
int root(int a)
{
if(r[a]==a) return a;
else return r[a]=root(r[a]);
}
void merge(int a,int b)
{
int ra,rb;
ra=root(a);
rb=root(b);
if(ra==rb) ans=0;//有环
else if(ra<rb)
r[rb]=ra;
else r[ra]=rb;
}
int main()
{
int i,flag,minn,maxx,x,y;
memset(vis,0,sizeof vis);
for(i=0;i<=100000;i++)
r[i]=i;
ans=1;minn=100005;maxx=0;
while(scanf("%d%d",&n,&m))
{
if(n==-1&&m==-1) break;
if(n==0&&m==0)
{
for(flag=0,i=minn;i<=maxx;i++)//看是否所有点都在一个集合内
{
if(r[i]==i&&vis[i])
flag++;
if(flag>1)
{
ans=0;
break;
}
}
if(ans)
printf("Yes\n");
else printf("No\n");
for(i=0;i<=100000;i++)
r[i]=i;
memset(vis,0,sizeof vis);
ans=1;minn=100005;maxx=0;
continue;
}
x=min(n,m);
y=max(n,m);
minn=min(minn,x);
maxx=max(maxx,y);
vis[n]=1;
vis[m]=1;
merge(n,m);
}
return 0;
}
原文:http://blog.csdn.net/u011032846/article/details/20479959