[CF788B Weird journey] 星際旅行(尤拉路)
阿新 • • 發佈:2020-09-10
CF788B [Weird Jouney]
一句話題意:總共有\(n\)個節點,\(m\)條路徑,要求其中\(m-2\)條路徑走兩遍,剩下\(2\)條路徑僅走一遍,問不同的路徑總數有多少,如果僅走一遍的兩條邊不同則將這兩條路徑視為不同。
Solution
直接把邊拆成兩條,顯然這樣每個點的度數都是偶數
整個圖構成尤拉路
題目意思就是說刪去兩條邊之後仍然構成尤拉路
那麼根據尤拉路的性質可以知道
刪去的兩條邊必連在同一個點上
這樣保證了有兩個點的度數變成奇數的情況下
和他們連的那個點度數-2,仍然為偶數
整張圖依然是尤拉路
下面考慮對答案有貢獻的三種情況\((circle為自環數量)\)
- 兩個自環對答案做貢獻,總貢獻\(\frac {circle * (circle - 1) } 2\)建議手模
- 一個自環一條邊,貢獻值\((circle) * (m - circle)\)
- 兩條邊\(\frac {(du[i] * (du[i] - 1)} 2\)
注意
- 統計答案開\(long \:\ long\),最後一種兩條邊的情況也要開
- 判斷整張圖是否連通,若不連通輸出0,可以選擇冰茶几或者dfs,總之隨便搞搞都能判
Code
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; inline int read(){ int x = 0, w = 1; char ch = getchar(); for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return x * w; } const int ss = 2000010; int fa[ss], du[ss]; inline int find(int u){ if(u == fa[u]) return u; return fa[u] = find(fa[u]); } inline void link(int u, int v){ int xx = find(u), yy = find(v); if(xx != yy) fa[xx] = yy; } long long ans; int l[ss], r[ss]; int circle; signed main(){ int n = read(), m = read(); for(int i = 1; i <= n; i++) fa[i] = i; for(int i = 1; i <= m; i++){ l[i] = read(), r[i] = read(); link(l[i], r[i]); if(l[i] == r[i]) circle++; else{ du[l[i]]++; du[r[i]]++; } } int begin = find(l[1]); for(int i = 2; i <= m; i++) if(find(l[i]) != begin) return puts("0"), 0; ans += (circle - 1) * circle / 2; ans += (circle) * (m - circle); for(int i = 1; i <= n; i++) ans += (long long)du[i] * (du[i] - 1) / 2; printf("%lld\n", ans); return 0; }