Codeforces Round #407 (Div. 1) B. Weird journey
阿新 • • 發佈:2019-01-14
題意
給定一個無重邊的圖(有自環),求有多少路徑滿足路徑遍歷所有的邊,並且有m-2條邊被遍歷兩次,2條邊被遍歷一次,兩條路路徑不同的定義是兩條路徑遍歷邊的集合不同?思路
遍歷所有的邊,想到歐拉回路,即一筆畫問題,一筆畫有兩種情況:(1)有且僅有兩個節點的度數為奇數(2)所有節點的度數均為偶數,題目要求m-2條邊都遍歷兩次, 不如先將所有的邊當作二重邊,那麼所有節點的度數都將翻倍,度數都變成了偶數,有兩條邊只遍歷一次,即把這兩條所連線的節點的度數減去1。假如減去度數後仍然能滿足尤拉圖的要求,有三種情況: (1)兩條只遍歷一次的邊(下稱‘’兩條邊‘’)為兩條相鄰的非自環邊 (2)兩條邊為一個自環和任意一條非自環邊 (3)兩條不同的自環邊 此外還要,判定所有邊是否都能被遍歷,與連通圖的判定類似。程式碼
#include<bits/stdc++.h> using namespace std; int n,m; vector<int>G[1000006]; int d[1000006]; bool vis[1000006]; int cnt; void dfs(int p) { cnt++; for(int i=0;i<G[p].size();i++) { int to=G[p][i]; if(!vis[to]) vis[to]=1,dfs(to); } } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=0;i<1000000;i++) G[i].clear(); memset(d,0,sizeof d); memset(vis,1,sizeof vis); long long ans=0; int num=0; for(int i=0;i<m;i++) { int u,v; scanf("%d %d",&u,&v); G[u].push_back(v); G[v].push_back(u); vis[u]=vis[v]=0; if(u!=v)ans+=d[u]+d[v],d[u]++,d[v]++; else num++; } ans+=1ll*num*(num-1)/2+1ll*num*(m-num); for(int i=1;i<=n;i++) if(!vis[i]) {vis[i]=0;dfs(i);break;} int cnt=0; for(int i=1;i<=n;i++) if(vis[i]) cnt++; if(cnt==n) printf("%I64d\n",ans); else puts("0"); } return 0; }