(((hdu3018连通分量的欧拉回路))

题目意思:

         有一个团队的人要去逛小镇,这个镇是无向图,然后规定每条路只能走一次,且两个小镇之间只有一条小路。(就避免了多条路径的问题。)然后这个图有可能有连通分量,如果图有孤立点,那么这个点就忽略掉,(这个挺有用)。问要分为几组人马才能够把这个城市的小镇全部逛完。

解题思路:(连通分量,粗俗地讲就是一个图的几个隔离的子图,每个子图为一个连通分量)

         这里有个公式:如果每个连通分量的节点的度为偶数,那么就可以一笔画,如果连通分量中的节点的度为奇数点个数除以2;由于题目的数据量有滴滴微大,节点数100000,边数200000;所以这里要用邻接表做,然后要算每一个连通分量,就要用到并查集了。
 
 
 

解题报告:

欧拉回路:图G,若存在一条路,经过G中每条边有且仅有一次,称这条路为欧拉路,如果存在一条回路经过G每条边有且仅有一次,

称这条回路为欧拉回路。具有欧拉回路的图成为欧拉图。

判断欧拉路是否存在的方法

有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。

无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。

判断欧拉回路是否存在的方法

有向图:图连通,所有的顶点出度=入度。

无向图:图连通,所有顶点都是偶数度。

 

本题呢。先用并查集查看共有几棵树, 记录下每棵树中度为奇数的点的个数。 如果该树中度为奇数的点的个数为0, 且代表元的度为0,证明该点为孤立的点,按题目要求的略过就可以了。如果代表元的度不为0, 且该树中度为奇数的店为0,那么证明为欧拉回路,1组就能搞定;如果这两种情况都不属于,那么浏览该树中的点要用奇数点的个数/2

代码如下:
 

 
 
#include<stdio.h>
#include<string.h>
int pre[100006];
int degree[100006];
int map[100006],ans[100006],p[100006];
int find(int k)
{
if(k!=pre[k])
pre[k]=find(pre[k]);
return pre[k];
}
int main()
{
int m,n,i,k,h,aa,bb,root,r,sum;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=1;i<=m;i++)
{
pre[i]=i;
degree[i]=0;
ans[i]=0;
p[i]=0;
}
for(i=1;i<=n;i++)
{
scanf("%d%d",&k,&h);
degree[k]++;
degree[h]++;
aa=find(k);
bb=find(h);
if(aa!=bb)
pre[aa]=bb;
}
r=0;
for(i=1;i<=m;i++)
{
root=find(i);
if(p[root]==0)
{
    p[root]=1;
map[r]=root; // vt保存着集合,集合就是图 
r++;
}
if(degree[i]%2==1)
ans[root]++; // 保存这个集合的奇数度数的个数 
}
sum=0;
for(i=0;i<r;i++)-----------对图进行处理。。
{
if(degree[map[i]]==0) // 孤立点 
continue;
if(ans[map[i]]==0) // 该集合是欧拉回路,有一条路
sum++;
else
sum=sum+(ans[map[i]]/2);//欧拉路径有s/2个;;
}
printf("%d\n",sum);
}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值