hdu 3018 Ant Trip (欧拉回路)

Description

hdu 3018 Ant Trip
Ant Country consist of N towns.There are M roads connecting the towns.

Ant Tony,together with his friends,wants to go through every part of the country.
这里写图片描述

Input

Input contains multiple cases.Test cases are separated by several blank lines.Each test case starts with two integer N(1<=N<=100000),M(0<=M<=200000),indicating that there are N towns and M roads in Ant Country.Followed by M lines,each line contains two integers a,b,(1<=a,b<=N) indicating that there is a road connecting town a and town b.No two roads will be the same,and there is no road connecting the same town.

Output

For each test case ,output the least groups that needs to form to achieve their goal.

Sample Input

3 3
1 2
2 3
1 3

4 2
1 2
3 4

Sample Output

1
2

Hint

New ~~~ Notice: if there are no road connecting one town ,tony may forget about the town.
In sample 1,tony and his friends just form one group,they can start at either town 1,2,or 3.
In sample 2,tony and his friends must form two group.

解题思路:先说明一下题意,就是有n个城市,有m条路,每条路都不能重复走,问需要出发几次才能把所有的路都走过一遍的。形象的就是说一笔画的问题,n个点,m个路线,一共需要几笔才能画完,是一道欧拉回路的简单扩展题目(欧拉回路,1.必须是连通图 2.所有点的度都必须是偶数)。
首先,我们要走的是这m条路,所以孤立存在的点就不用考虑了,然后对于单独存在的欧拉回路出现一次就可以记上一次,但是要知道,每一个小的欧拉回路必须要单独存在。如果与其他路线相连,只需要计算上一次就可以了。然后考虑的就是欧拉回路之外的点了,他们就是那些度为奇数的点,出现一次就统计一次,最后奇数度点数/2+单独存在欧拉回路数就是结果了。为什么奇数度点的个数要除以2呢,因为奇数度的点就只能经过奇数次,不像偶数度,走过去之后还能往回走。经过奇数次之后就回不去了,也就是到达了另外一个奇数度的点,出现了两个奇数度的点但是存在于一笔之中。所以这里除以2就可以了。
总笔画数=奇数度点数/2+单独存在欧拉回路数。

AC代码

#include <stdio.h>
#include <string.h>
int pur[100010];	//并查集数组标记父亲
int f[100010];		//存储每个点的度
int mark[100010];	//标记父亲这一点是否已经走过

int find(int x)
{
	if(x==pur[x])
		return x;
	return find(pur[x]);
}
void merge(int x,int y)
{
	int t;
	int u=find(x);
	int v=find(y);
	if(u<v)
		t=v,v=u,u=t;
	pur[u]=v;
	return ;
}

int main()
{
	int n,m,a,b;
	int i,j,yy;
	while(scanf("%d%d",&n,&m)!=EOF){
		for(i=1;i<=n;i++)  //数据初始化
			pur[i]=i;
		memset(f,0,sizeof(f));
		memset(mark,0,sizeof(mark));
		for(i=0;i<m;i++){
			scanf("%d%d",&a,&b);
			f[a]++;			//记录每个点的度 
			f[b]++;
			merge(a,b);		//合并两个点 
		}
		yy=0;
		for(i=1;i<=n;i++){
			if(f[i]%2){		/*判断该点度数如果为奇数
			就加上去,然后将其父亲标记为1 */
				yy++;
				mark[find(i)]=1;
			}
		}
		yy/=2;
		for(i=1;i<=n;i++){
			if(!f[i])    //单独存在的点没有路,直接跳过即可
				continue;
			if(mark[find(i)]==0&&find(i)==i)
				yy++; 	 	/*如果这个点与其他点能构
	成欧拉回路的话(也就是能够一笔画成),并且与奇数度不相连的话就需要重新开
	一条路,这时候yy才会自增。如果相连的话mark就已经将其父亲标记为1了,
	就在奇数度的时候已经计算过就不用加了。*/
		}
		printf("%d\n",yy);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值