原題目地址ios
一句話題意:總共有\(n\)個節點,\(m\)條路徑,要求其中\(m-2\)條路徑走兩遍,剩下\(2\)條路徑僅走一遍,問不一樣的路徑總數有多少,若是僅走一遍的兩條邊不一樣則將這兩條路徑視爲不一樣。spa
直接把邊拆成兩條,顯然這樣每一個點的度數都是偶數
整個圖構成歐拉路
題目意思就是說刪去兩條邊以後仍然構成歐拉路
那麼根據歐拉路的性質能夠知道
刪去的兩條邊必連在同一個點上
這樣保證了有兩個點的度數變成奇數的狀況下
和他們連的那個點度數-2,仍然爲偶數
整張圖依然是歐拉路
code
下面考慮對答案有貢獻的三種狀況\((circle爲自環數量)\)blog
注意ci
#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; }