无向图,n个点m条边。问至少添加几条边,使得图有奇环(不能是单个点),有几种添加方法。
这里用到了一个很重要的定理:二分图没有奇环。给图染色判断是不是二分图。然后分类讨论。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=100010;
ll n,m;
vector<int> E[maxn];
int color[maxn];
bool flag;
int tot;
ll part1,part2;
void dfs(int u,int pre){
tot++;
color[u]=!color[pre];
if(color[u]==1)part1++;
else part2++;
for(int i=0;i<E[u].size();i++){
int v=E[u][i];
if(v==pre)continue;
if(-1!=color[v]){
if(color[v]==color[u]){
flag=1;
return;
}
}else{
dfs(v,u);
}
}
}
int main(){
memset(color,-1,sizeof(color));
color[0]=0;
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
}
ll ans=0,ans2=0;
for(int i=1;i<=n;i++){
tot=0;
part1=part2=0;
if(-1==color[i]){
dfs(i,0);
}
if(tot>2){
ans+=part1*(part1-1)/2;
ans+=part2*(part2-1)/2;
}else if(tot==2){
ans2+=(n-2);
}
}
if(flag){
printf("0 1\n");
}else{
if(m==0){
printf("3 %I64d\n",n*(n-1)*(n-2)/6);
}else{
if(ans){
printf("1 %I64d\n",ans);
}else{
printf("2 %I64d\n",ans2);
}
}
}
return 0;
}