思路:我们可以这样想,那m-2条边经过两次等价于有两条m-2条边都分别经过了一次,然后题目就转化成经过所有2m-2条边一次的走法有多少种,也就是欧拉路有几条。欧拉路的条件是要满足奇数度节点为0或2。然后我们来分析一下,若图是不联通的,答案肯定为0,若图是联通的,我们先假设有2m条边(也就是把每条边都增加一条),那么奇数度节点为0。因为我们要选择两条边只经过一次,也就是去掉两条边之后要符合欧拉路条件,因为题目说明有自环边,所以有以下4种情况,去掉相邻的两条普通边,奇数度节点为2,符合欧拉路条件;去掉不相邻的两条普通边,奇数度节点为4,不符合欧拉路条件;去掉一条自环边和一条普通边,奇数度节点为2,符合欧拉路条件;去掉两条自环边,奇数度节点为0,符合欧拉路条件。剩下的就是单纯的统计了,这题还有个坑就是所有的边里面不一定包含n个点,也就是他给你m条边,有可能点1没有在里面,但他还是联通的。下面给代码:
#include<iostream>
#include<cmath>
#include<queue>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<utility>
#include<map>
#include<set>
#define maxn 1000005
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
const double eps=1e-8;
const LL mod=1e9+7;
int vis[maxn],deg[maxn],n,m,len,head[maxn],loop[maxn];
struct node{
int v,next;
}p[maxn<<1];
void addedge(int u,int v){
p[len].v=v;
p[len].next=head[u];
head[u]=len++;
}
void dfs(int x){
vis[x]=1;
for(int i=head[x];~i;i=p[i].next){
if(vis[p[i].v])
continue;
dfs(p[i].v);
}
}
int main(){
memset(head,-1,sizeof(head));
int num=0;
LL sumloop=0;
LL ans=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
if(u==v){
sumloop++;
loop[u]++;
continue;
}
addedge(u,v);
addedge(v,u);
deg[u]++;
deg[v]++;
}
for(int i=1;i<=n;i++){
if((deg[i]||loop[i])&&!vis[i]){
dfs(i);
num++;
}
}
if(num>1){
printf("0\n");
return 0;
}
for(int i=1;i<=n;i++)
ans+=(LL)deg[i]*(deg[i]-1)>>1;
ans+=sumloop*(sumloop-1)>>1;
ans+=sumloop*(m-sumloop);
printf("%lld\n",ans);
}