一开始没有思路,以为要判联通块。
其实不是判断联通块,而是判断边是否连在一起,没有连边的点可以忽略不计
/* 分情况讨论: 1.忽略自环,那么要取出两条相连的普通变作为只经过一次的边 2.一条自环,一条普通边 3.两条自环 自环独立存储 */ #include<bits/stdc++.h> using namespace std; #define maxn 1000005 #define ll long long struct Edge{ int to,next; }edge[maxn<<1]; int n,m,u,v,head[maxn],tot,vis[maxn],degree[maxn],f[maxn],num1,num2; void dfs(int u){ vis[u]=1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(!vis[v])dfs(v); } } void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } int main(){ scanf("%d%d",&n,&m); memset(head,-1,sizeof head); memset(degree,0,sizeof degree); memset(f,0,sizeof f); memset(vis,0,sizeof vis); tot=num1=num2=0; for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); if(v==u)f[u]=1,num1++; else { addedge(u,v); addedge(v,u); num2++; degree[u]++; degree[v]++; } } for(int i=1;i<=n;i++) if(degree[i]){//从第一个和其他点有边的点开始 dfs(i);break; } for(int i=1;i<=n;i++) if(!vis[i] && (degree[i] || f[i])){ puts("0");return 0; } ll ans=0; for(int i=1;i<=n;i++) ans+=(ll)degree[i]*(degree[i]-1)/2; ans+=(ll)num1*num2+(ll)num1*(num1-1)/2; printf("%lld ",ans); }