ZOJ 3321 Circle(并查集)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3321
题意:
给你一个n节点m条边的无向图,问你该图是否正好是一个环(输入不存在自环,没有重复边)?
分析:
无向图是一个简单环 充要条件是 所以节点的度数==2 且 图连通.
所以我们只需要记录每个节点的度且用并查集判断最终全图是否只有1个连通分量 即可.
AC代码(新):
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=50+5;
int n,m;
int degree[maxn];
int fa[maxn];
int findset(int x)
{
return fa[x]==-1? x:fa[x]=findset(fa[x]);
}
int bind(int u,int v)
{
int fu=findset(u);
int fv=findset(v);
if(fu != fv)
{
fa[fu]=fv;
return 1;
}
return 0;
}
bool ok()
{
for(int i=1;i<=n;i++)
if(degree[i]!=2) return false;
for(int i=2;i<=n;i++)
if(findset(i) != findset(1)) return false;
return true;
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
memset(fa,-1,sizeof(fa));
memset(degree,0,sizeof(degree));
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
degree[u]++;
degree[v]++;
bind(u,v);
}
printf("%s\n",ok()?"YES":"NO");
}
return 0;
}
AC代码:
#include<cstdio>
using namespace std;
const int maxn=100+5;
int degree[maxn];
int fa[maxn];
int findset(int x)
{
return fa[x]==-1?x:fa[x]=findset(fa[x]);
}
void bind(int i,int j)
{
int fi=findset(i);
int fj=findset(j);
if(fi!=fj)
{
fa[fi]=fj;
}
}
bool ok(int n)
{
for(int i=1;i<=n;++i)
if(degree[i]!=2) return false;
int root=fa[1]==-1?1:fa[1];
for(int i=2;i<=n;++i)
if(findset(i)!=root) return false;
return true;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
for(int i=1;i<=n;++i)
{
degree[i]=0;
fa[i]=-1;
}
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
++degree[u];
++degree[v];
bind(u,v);
}
printf("%s\n",ok(n)?"YES":"NO");
}
return 0;
}