[歐拉回路] CF209C Trails and Glades
阿新 • • 發佈:2020-07-27
填個遠古的巨坑。。。。
主要是這題和當年考的題題面有點出入不然早改好直接交了
碼風比較遠古
/* 並查集維護連通塊 跑一遍圖 記錄每個點度數需 要加的邊數為 (偶數度數連通塊數) + (奇數度數點數) / 2 -> 多個連通塊時 或 (奇數點數個數) / 2 -> 單個連通塊時 注意可能有重邊和自環 -> 這題和模擬賽不同,它只要求存在歐拉回路 百度學長 如果圖G中的一個路徑包括每個邊恰好一次,則該路徑稱為尤拉路徑(Euler path)。 如果一個迴路是尤拉路徑,則稱為歐拉回路(Euler circuit)。 也就是說歐拉回路不需要考慮單獨的點 但是自環的點還是要考慮的 */ # include <iostream> # include <cstdio> # include <cstring> using namespace std; # define MAXN 1000005 int n, m, degree[MAXN]; bool vis[MAXN]; // Union-Find Set int sum[MAXN]; int size[MAXN], fa[MAXN]; void init_ufs(int x){ memset(vis, 0 ,sizeof(vis)); for(int i = 1; i <= n; i++){ size[i] = 1; fa[i] = i; } } int find(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); } void merge(int x, int y){ x = find(x); y = find(y); if(x == y) return; if(size[x] > size[y]){ fa[y] = x; size[x] += size[y]; } else{ fa[x] = y; size[y] += size[x]; } } // Main Function int main(){ int a, b; scanf("%d%d", &n, &m); init_ufs(n); vis[1] = 1; // 注意! ////////// for(int i = 1; i <= m; i++){ scanf("%d%d", &a, &b); degree[a]++, degree[b]++; a = find(a), b = find(b); if(a != b) merge(a, b); vis[size[a] > size[b] ? a : b] = 1; } int cnt = 0, ans = 0; for(int i = 1; i <= n; i++){ if(i == find(i) && vis[find(i)]){ cnt += 1; } } if(!vis[find(1)]){ cnt += 1; // 注意和模擬賽不同的是這題要求必須過一號節點 } for(int i = 1; i <= n; i++){ if(degree[i] % 2){ sum[find(i)] += 1; } } if(cnt == 1){ cout<<sum[find(1)] / 2; return 0; } for(int i = 1; i <= n; i++){ if(vis[i] && find(i) == i){ ans += sum[i] / 2; if(!sum[i]){ ans += 1; } } } cout<<ans; return 0; }