Ant Trip 題解
阿新 • • 發佈:2020-08-20
Ant Trip
分析
題意很簡單,爆搜的時間複雜度比較高,不考慮。
應該使用歐拉回路的相關知識求解。
intn()
輸入時將兩個節點的入度都加一(無向),然後將兩個節點合併在一個連通圖中.
for (int i = 1, u, v; i <= m; i++) {
scanf ("%d %d", &u, &v);
in[v] ++, in[u] ++;
UnionSet(u, v);
}
work()
step1
從1~n迴圈,依次列舉,記錄每個連通圖中的點數。
用一個ans[]陣列儲存連通圖中度為奇數的節點。
step2
再列舉一遍
如果一個連通圖中的節點數不大於1,就不用畫,跳過。
如果ans[]為0,這次圖是一個歐拉回路,就sum++
如果ans[]不為零 sum += ans[]/2
因為一筆只能夠畫掉兩個奇數度數的節點(因為TFW不停問,特此強調),所以只加上ans[]/2
程式碼
#include <vector> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 1e5 + 5; int n, m, sum; int in[MAXN], num[MAXN], ans[MAXN], fa[MAXN]; /* num -> 儲存一個連通塊裡有幾個節點*/ int FindSet(int v) { if (fa[v] == v) return v; else return fa[v] = FindSet(fa[v]); } void UnionSet(int u, int v) { int x = FindSet(u); int y = FindSet(v); if (x == y) return ; else fa[x] = y; } int main() { while (scanf ("%d %d", &n, &m) != EOF) { sum = 0; for (int i = 1; i <= n; i++) { fa[i] = i; ans[i] = 0; num[i] = 0; in[i] = 0; } for (int i = 1, u, v; i <= m; i++) { scanf ("%d %d", &u, &v); in[v] ++, in[u] ++; UnionSet(u, v); } for (int i = 1; i <= n; i++) { num[FindSet(i)] ++; if (in[i] % 2 == 1) { ans[FindSet(i)] ++; } } for (int i = 1; i <= n; i++) { if (num[i] <= 1) continue; if (ans[i] == 0) sum ++; else { sum += ans[i] / 2; } } printf ("%d\n", sum); } return 0; }