经典题目,HDU上也有,给定一个无向图,先判断是否为二分图,不是输出No,是的话,输出最大匹配,算是一个模板题
1.一个图不存在奇环则是二分图
2.二分图最大匹配用匈牙利算法
#include <cstdio> #include <cstring> #define N 210 int g[N][N]; //无向图领接表 int mat[N],cov[N],vis[N],c[N]; int n,m; void input() { memset(g,0,sizeof(g)); for(int i=1; i<=m; i++) { int u,v; scanf("%d%d",&u,&v); int t; t=++g[u][0]; g[u][t]=v; t=++g[v][0]; g[v][t]=u; } return ; } int dfs(int u ,int p) //u是当前顶点,p是它的前驱,c表示奇偶 { vis[u]=1; for(int i=1; i<=g[u][0]; i++) { int v=g[u][i]; if(v==p) continue; //如果是前驱跳过,不能走回头 if(vis[v]==0) //还没访问过的点,直接访问 { c[v]=!c[u]; if(dfs(v,u)) return 1; } else if(vis[v]==1) //已经访问过,那么就是环,那么就判断是不是奇环 { if( c[u]==c[v] ) //加上成环的边后是奇数,那么就是奇环 return 1; } } return 0; } int find(int u) { for(int i=1; i<=g[u][0]; i++) { int v=g[u][i]; if(!cov[v]) { cov[v]=1; if(!mat[v] || find(mat[v])) { mat[v]=u; return 1; } } } return 0; } void max_match() { int ans=0; memset(mat,0,sizeof(mat)); for(int i=1; i<=n; i++) { memset(cov,0,sizeof(cov)); ans+=find(i); } /* printf("mat数组\n"); for(int i=1; i<=n; i++) printf("%d ",mat[i]); printf("\n"); printf("ans=%d\n",ans); */ printf("%d\n",ans/2); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { input(); memset(vis,0,sizeof(vis)); memset(c,0,sizeof(c)); int flag=1; for(int i=1; i<=n; i++) if(!vis[i]) { if(dfs(i,0)) {flag=0; break;} } if(!flag) printf("No\n"); else max_match(); } return 0; }