hdu--3018

Ant Trip

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2156    Accepted Submission(s): 831


Problem Description
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. 

They intend to visit every road , and every road must be visited for exact one time.However,it may be a mission impossible for only one group of people.So they are trying to divide all the people into several groups,and each may start at different town.Now tony wants to know what is the least groups of ants that needs to form to achieve their goal.
 

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笔画出,则N必然是自然数(即要么1笔画出来,要么2笔画出来,而不可能是1笔半).而任何1笔,必然有且只有1个起点和1个终点(如果起点和终点在同一点,也是有1个起点和1个终点的,只不过重合了而已,注意!). 所以,N笔的所有起点数和终点数之和,必然是2N. 而图形的奇点,则是由笔划的起点和终点组成的. 由于偶点发出的线条为偶数,所以:要么偶点既不是笔划的起点又不是终点,要么就是包含着偶数个起点(或终点),即偶点中起点数+终点数必然是偶数,设这个偶数为2X. 从以上分析可以知道,奇点的数目,就是2N减去偶点中起点和终点数,而偶点中起点数+终点数为偶数2X,所以奇点数=2N-2X=2(N-X),即奇点数必然为偶数.

问题可以转换成至少用多少笔画出这个图。计算出图一共有几块连通块,判断每一块连通块是否有奇数度的点。有奇数度的点,奇数度点/2。否则+1;将上述结果加起来,就是最后的结果来,(忽略孤立点)。

代码如下:

#include<stdio.h>
int num[100000+10];//村庄 
int per[100000+10];
int sum[100000+10];
int d[100000+10];
void inin(){
    for(int i=0;i<=100000;i++){
        per[i]=i;
        num[i]=0;
        sum[i]=0;
        d[i]=0;
    }
}
int find(int x){
    return per[x]=x==per[x]?x:find(per[x]);
}
void judge(int x,int y){
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy){
        per[fx]=fy;
    }
}
int  join(int k){
    int flag=0;
    for(int i=0;i<k;i++){
          if(d[sum[i]]%2){
              flag++;
              int x=find(sum[i]);
              num[x]=-1;
          }
    }
    flag/=2;
    for(int i=0;i<k;i++){
        if(per[sum[i]]==sum[i]&&num[sum[i]]!=-1){
            flag++;
        }
    }
    return flag;
}
int main(){
    int a,b,n,m,k;
    while(scanf("%d%d",&n,&m)!=EOF){
       inin();
       k=0;
       for(int i=1;i<=m;i++){
           scanf("%d%d",&a,&b);
           if(!num[a]){
               num[a]=1;
               sum[k++]=a;
           }
           if(!num[b]){
               num[b]=1;
               sum[k++]=b;
           }
           d[a]++;d[b]++;
        judge(a,b);
      }
       printf("%d\n",join(k)); 
    }
    return 0;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值