hdu3018 2010.3.3
Hdu 3018
【关键字】
压缩路径的并查集+欧拉路
【摘要】
给定若干个图,求最少用几笔可将其画完(遍历所有的边,且仅遍历一次)。
【正文】
1、题目描述
Ant Trip
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 122 Accepted Submission(s): 52
ProblemDescription
Ant Country consist of N towns.There are Mroads connecting the towns.
Ant Tony,together with his friends,wants togo through every part of the country.
They intend to visit every road , and everyroad must be visited for exact one time.However,it may be a mission impossiblefor only one group of people.So they are trying to divide all the people intoseveral groups,and each may start at different town.Now tony wants to know whatis the least groups of ants that needs to form to achieve their goal.
Input
Input contains multiple cases.Test casesare separated by several blank lines. Each test case starts with two integerN(1<=N<=100000),M(0<=M<=200000),indicating that there are N townsand M roads in Ant Country.Followed by M lines,each line contains two integersa,b,(1<=a,b<=N) indicating that there is a road connecting town a andtown b.No two roads will be the same,and there is no road connecting the sametown.
Output
For each test case ,output the least groupsthat needs to form to achieve their goal.
SampleInput
3 3
1 2
2 3
1 3
4 2
1 2
3 4
SampleOutput
1
2
Hint
New ~~~ Notice: if there are no roadconnecting one town ,tony may forget about the town.
In sample 1,tony and his friends just formone group,they can start at either town 1,2,or 3.
In sample 2,tony and his friends must formtwo group.
Source
2009 Multi-University Training Contest 12 -Host by FZU
Recommend
gaojie
2、算法分析
这道题的本质就是若干个图的min笔画问题,要求min最小。
首先要确定有几个独立的图,用到了并查集,而且还是压缩路径的。
对于每个图,如果只有偶点,那么可以一笔画;若有n个奇点,那最少要用n/2笔。
其实,比赛的时候想到了这样做,只是不会用并查集,所以,没有办法实现。写这道题的解题报告的原因就是,我学会了用压缩路径的并查集。
3、源码
#include <stdio.h>
#include <string.h>
#define MAXN 100000+10
int father[MAXN],num[MAXN],used[MAXN],ans,count[MAXN];
int n,m,i,j,a,p,b,fa,fb;
int find(int x)
{
if (father[x]==x) return x;
father[x]=find(father[x]);
return father[x];
}
void main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
ans=0;
for(i=1;i<=n;i++)
father[i]=i;
memset(num,0,sizeof(num));
memset(used,0,sizeof(used));
memset(count,0,sizeof(count));
for(j=1;j<=m;j++)
{
scanf("%d %d",&a,&b);
fa=find(a);
fb=find(b);
if (fa!=fb)
father[fa]=fb;
used[a]++;
used[b]++;
}
for(j=1;j<=n;j++)
{
if (used[j])
{
p=find(j);
count[p]++;
if (used[j]%2==1)
num[p]++;
}
}
for(j=1;j<=n;j++)
{
if (count[j])
{
if (num[j]==0)
ans++;
else
ans+=num[j]/2;
}
}
printf("%d\n",ans);
}