题意简述
给定一个图 求至少添加多少条边使得它存在奇环 并求出添加的方案数
(注意不考虑自环)
-----------------------------------------------------------------------------
一道二分图染色的讨论题
比赛时只会用二分图染色判断树以及偶环 忘记用这个来判奇环。。。
二分图染色这种联赛知识点的题目现在也不会写了。。。
------------------------------------------------------------------------------
我们可以按需要添加边的条数来讨论这题
首先讨论添加边条数为3——即原原图边数m为0时
ns=n*(n-1)*(n-2)/6
再讨论添加边条数为2——即原图中所有边都没有公共端点/所有点度数<=1 时
ans=m*(n-2)
再讨论添加边数为0——即原图中存在奇环时
ans=1
最后讨论添加边数为1——即原图中只有树以及偶环
ans=Σ(white[i]-1)*white[i]/2+(black[i]-1)*black[i]/2
其实思路清晰后实现起来就很容易了
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define rep(i,n) for(int i=1;i<=n;++i) #define imax(x,y) (x>y?x:y) #define imin(x,y) (x<y?x:y) using namespace std; const int N=100010; int firste[N],nexte[N<<1],v[N<<1]; int color[N],fa[N],bl[N],wh[N],degree[N]; int n,m,e=1,flag=1; long long ans=0; void build_edge(int x,int y) { ++e; nexte[e]=firste[x]; firste[x]=e; v[e]=y; } void dfs(int u,int c,int f) { color[u]=c; fa[u]=f; if(c&1)++bl[f]; else ++wh[f]; for(int p=firste[u];p;p=nexte[p]) if(!color[v[p]])dfs(v[p],3-c,f); else if(color[v[p]]==color[u]) { flag=1; return; } } int main() { int x,y; scanf("%d%d",&n,&m); if(!m) { ans=(long long)n*(n-1)*(n-2)/6; printf("3 %I64d",ans); return 0; } rep(i,m) { scanf("%d%d",&x,&y); build_edge(x,y); build_edge(y,x); ++degree[x]; ++degree[y]; if(degree[x]>1||degree[y]>1)flag=0; } if(flag) { ans=(long long)m*(n-2); printf("2 %I64d",ans); return 0; } int cnt=0; rep(i,n) if(!color[i]) { dfs(i,1,++cnt); if(flag) { printf("0 1"); return 0; } } rep(i,cnt) ans+=(long long)(wh[i]-1)*wh[i]/2+(long long)(bl[i]-1)*bl[i]/2; printf("1 %I64d",ans); return 0; }
时间: 2024-10-11 03:38:03