백준18250 철도 여행

문제 링크

  • http://icpc.me/18250

문제 출처

  • Good Bye, BOJ 2019 D번

사용 알고리즘

  • Union Find
  • Euler Tour

풀이

주어진 그래프가 connected가 아니라면 각 컴포넌트에 대해 정답을 구해서 합치면 되기 때문에, connected graph만 고려합시다.

각 컴포넌트에 대해 정답은

  • 컴포넌트에 홀수 차수 정점이 있다면 (홀수 정점 개수) / 2
  • 그렇지 않을 경우, 간선이 있다면 1 / 그렇지 않다면 0

입니다.

트레일을 끝내고 새로운 트레일을 시작하는 것을 간선을 적절히 하나 추가하는 것이라고 생각하면 편합니다.

전체 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <bits/stdc++.h>
using namespace std;

int par[202020];
int sz[202020];
int odd[202020];
int deg[202020];

int s[303030], e[303030];

int n, m;

void init(){ for(int i=0; i<202020; i++) par[i] = i, sz[i] = 1, odd[i] = 0; }
int find(int v){ return v == par[v] ? v : par[v] = find(par[v]); }
void merge(int u, int v){ u = find(u), v = find(v); if(u ^ v) par[u] = v, sz[v] += sz[u], odd[v] += odd[u]; }

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    init();
    cin >> n >> m;
    for(int i=0; i<m; i++){
        cin >> s[i] >> e[i];
        deg[s[i]]++; deg[e[i]]++;
    }
    for(int i=1; i<=n; i++){
        odd[i] = deg[i] & 1;
    }
    for(int i=0; i<m; i++){
        merge(s[i], e[i]);
    }
    int ans = 0;
    for(int i=1; i<=n; i++){
        int v = find(i);
        if(i ^ v) continue;
        if(sz[v] == 1) continue;
        if(!odd[v]) ans++;
        else ans += odd[v] / 2;
    }
    cout << ans;
}