HDU 3018 Ant Trip【歐拉回路】【經典一筆畫問題】

Ant Trip

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

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.

題意: 給你一個圖,以及一些邊,問你需要多少個人可以走完所有的邊, 類似於一筆畫。

分析:
思路:
常規題的思路,我們還可以發現在一個集合中如果存在奇點, 那麼在這個集合中需要 (奇點個數 / 2) 筆 即可畫完,因爲一個集合中奇點的個數始終爲偶數,所以直接統計整個圖中的奇點個數即可, (代碼裏面的t) 還有考慮集合中不存在奇點的集合,這種情況的只需要一筆即可(也就是裏面的sum)

ps:還有一個思路就是不用set統計每個集合中的具體元素,只需要標記下那些奇點所在的集合(標記下根節點即可),然後在最後只需統計沒有標記的根節點 這裏注意一定要check 孤立的點!

參考代碼

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 10;


/***
    一筆畫問題,給你一個圖,讓你判斷最少需要幾筆畫完,孤立的點不用畫。


    思路:我們還可以發現在一個集合中如果存在奇點,
    那麼在這個集合中需要   (奇點個數 / 2)  筆 即可畫完,
    因爲一個集合中奇點的個數始終爲偶數,所以直接統計整個圖中的
    奇點個數即可,  (代碼裏面的t)
    還有考慮集合中不存在奇點的集合,這種情況的只需要一筆即可(也就是裏面的sum)


    ps:還有一個思路就是不用set統計每個集合中的具體元素,只需要標記下那些
    奇點所在的集合(標記下根節點即可),然後在最後只需統計沒有標記的根節點
    這裏注意一定要check 孤立的點!

*/


/**
    f : 並查集中,存儲 i個節點的父親節點
    e : 存儲每個集合
    len : 每個節點的 入度+出度
*/

int f[maxn];
set<int> e[maxn];
int len[maxn];

void init() {
    for (int i = 0; i < maxn; i++){
        f[i] = i;
        e[i].clear();
        len[i] = 0;
    }
}

int fa(int x) {
    return x == f[x] ? x : f[x] = fa(f[x]);
}

int main(){
    int n,m;
    while (scanf("%d%d", &n, &m) != -1) {
        init();
        for (int i = 0; i < m; i++) {
            int x, y; scanf("%d%d", &x, &y);
            len[x]++,len[y]++;
            int fx = fa(x);
            int fy = fa(y);
            f[fx] = fy;
        }
        int t = 0;
        for (int i = 1; i <= n; i++) {
            f[i] = fa(i);
            if (len[i] & 1) t++;
        }
        for (int i = 1; i <= n; i++) e[f[i]].insert(i);
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            if (e[i].size() > 2) { /// 這裏注意check
                int odd = 0;
                for (auto it : e[i]) if (len[it] & 1) odd++;
                if (!odd) sum++;
            }
        }
        cout << sum + t / 2<< endl;
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章