hdu 1272 并查集判环 无向图 连通性+无环
易错点:1、忘了考虑不能是森林 有多个根结点 或 结点数=边数+1 即判断连通性
2、样例为0 0应该是Yes,空树
#include<cstdio>
//数组应该开多大?
//不满足树的判定:1、有两个父亲
using namespace std;
//vector<int> fa;
const int N=1e5+10;
int fa[N],vis[N];
int flag=1;
void init()
{
for(int i=1;i<=N;++i)
{
fa[i]=i;
vis[i]=0;
}
}
int find(int x)
{
if(x==fa[x])
return x;
else
return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
fa[fy]=fx;
}
else
flag=0;
}
int main()
{
int a,b;
while(scanf("%d%d",&a,&b)!=EOF) //如果a==0,b==0
{
init();
flag=1;
if(!(a+b)){printf("Yes\n");continue;}
if(a==-1&&b==-1) break;
merge(a,b);
vis[a]=vis[b]=1;
while(scanf("%d%d",&a,&b)!=EOF&&(a+b))
{
if(flag)
{
merge(a,b);
vis[a]=vis[b]=1;
}
}
int cnt=0;
for(int i=1;i<=N;++i)
{
if(vis[i]&&i==fa[i])
{
++cnt;
}
// if(cnt>1)
// break; 为啥注释掉这个就对了啊!麻蛋
}
if(flag&&cnt==1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
hdu 1325 判断是不是树 1、有向图判环 2、连通
与无向图的区别在于(x->y):在合并的时候,我把fy挂在fx下,要保证对fy是第一次操作,即保证没有两个节点是指向y的
if(fx==fy||y!=fy) y!=fy说明有多个节点指向y
#include<cstdio>
using namespace std;
const int N=1e5+10;
int fa[N],vis[N];
int flag=1;
void init()
{
for(int i=1;i<=N;++i)
{
fa[i]=i;
vis[i]=0;
}
}
int find(int x)
{
if(x==fa[x])
return x;
else
return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy||y!=fy) //y!=fy说明被更新两次 这两个if顺序写反了也会wa
flag=0; //不能用vis[y]来判断是否更新多次 因为比如根结点啊,本来就会出现很多次
if(fx!=fy)
{
fa[fy]=fx;
}
}
int main()
{
int a,b;
int kase=0;
while(scanf("%d%d",&a,&b)!=EOF) //如果a==0,b==0
{
init();
flag=1;
if(!(a+b)){printf("Case %d is a tree.\n",++kase);continue;}
if(a<0&&b<0) break;
merge(a,b);
vis[a]=vis[b]=1;
while(scanf("%d%d",&a,&b)!=EOF&&(a+b))
{
if(flag)
{
merge(a,b);
vis[a]=vis[b]=1;
}
}
int cnt=0;
for(int i=1;i<=N;++i)
{
if(vis[i]&&i==fa[i])
{
++cnt;
}
//
}
if(flag&&cnt==1)
printf("Case %d is a tree.\n",++kase);
else
printf("Case %d is not a tree.\n",++kase);
}
return 0;
}