CodeForces788B 欧拉路
题意:
有n个点,m条边,问如果选择m-2条边走2次,2条边只走1次,一共有多少种走法(当且仅当只走一次的边的集合不相同时,走法才不相同)
题解:
可以这样想,其它边走两次,就是说,一次去,一次回来。
如果图不连通,那么绝对是0,每条边经过两次,遍历整个图,那是局对可行的,
因为这样就是边重复走一次,求欧拉回路,那是绝对可以的,去在回来不久行了,只要连通随便走。
这样两条边只经过一次,如果有自环,自环多余两个随便选两个都可以,
选一个自环其它随便选一条边也可以,
不然,就只能两条边同一端点才行,统计答案。
1 #include<cstring> 2 #include<algorithm> 3 #include<cmath> 4 #include<iostream> 5 #include<cstdio> 6 #define ll long long 7 #define N 1000007 8 using namespace std; 9 10 int n,m,t; 11 ll du[N]; 12 int zh[N]; 13 bool vis[N]; 14 int cnt,head[N],next[N*2],rea[N*2]; 15 16 void add(int u,int v) 17 { 18 next[++cnt]=head[u]; 19 head[u]=cnt; 20 rea[cnt]=v; 21 } 22 void dfs(int u) 23 { 24 vis[u]=true; 25 for (int i=head[u];i!=-1;i=next[i]) 26 { 27 int v=rea[i]; 28 if (!vis[v]) dfs(v); 29 } 30 } 31 int main() 32 { 33 memset(head,-1,sizeof(head)); 34 scanf("%d%d",&n,&m); 35 for (int i=1,x,y;i<=m;i++) 36 { 37 scanf("%d%d",&x,&y); 38 add(x,y),add(y,x); 39 if (x==y) 40 { 41 t++; 42 zh[x]++; 43 continue; 44 } 45 du[x]++,du[y]++; 46 } 47 for (int i=1;i<=n;i++) 48 if (du[i]) 49 { 50 dfs(i); 51 break; 52 } 53 for (int i=1;i<=n;i++) 54 if (!vis[i]) 55 { 56 if (du[i]||zh[i]) 57 { 58 printf("0\n"); 59 return 0; 60 } 61 } 62 ll ans=0; 63 ans+=(ll)t*(t-1)/2;//自环随便选。 64 ans+=(ll)t*(m-t);//其它点随便选、 65 for (int i=1;i<=n;i++) 66 if (du[i]>=2) ans+=(ll)du[i]*(du[i]-1)/2;//表示一条边进,一条边出。 67 printf("%lld",ans); 68 }