题意:给出n个点,m条边,问是否是二分图,不是输出No,如果是输出二分图最大匹配。
思路:先判断是否是二分图。这里运用染色法,这里用的dfs(用bfs也可以),原理就是相连两点不能是同一种颜色。
二分图最大匹配用匈牙利算法就行。具体看代码。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<vector> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; int color[250]; int mat[250]; int used[250]; int n,m; vector<int> ve[250]; bool dfs(int x,int c)//染色 { color[x]=c; int s=ve[x].size(); for(int i=0;i<s;i++) { if(color[ve[x][i]]==c)//相连点同样颜色,不是二分图 return false; if(color[ve[x][i]]==0&&!dfs(ve[x][i],-c))//相连点还未染色,搜索相连点 return false; } return true; } bool solve()//判断是否是二分图 { memset(color,0,sizeof(color)); for(int i=1;i<=n;i++) { if(!color[i]) { if(!dfs(i,1)) return false; } } return true; } //匈牙利算法 bool find(int x) { int s=ve[x].size(); for(int i=0;i<s;i++) { int v=ve[x][i]; if(!used[v]) { used[v]=1; if(!mat[v]||find(mat[v])) { mat[v]=x; return true; } } } return false; } int match() { int ans=0; memset(mat,0,sizeof(mat)); for(int i=1;i<=n;i++) { memset(used,0,sizeof(used)); if(find(i)) ans++; } return ans; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { int u,v; for(int i=1;i<=n;i++) ve[i].clear(); for(int i=0;i<m;i++) { scanf("%d%d",&u,&v); ve[u].push_back(v); ve[v].push_back(u); } if(!solve()) printf("No "); else printf("%d ",match()/2); } return 0; }