题意:
有N个女生想跟自己的一个或者多个男生做在一起。然后要你算出最后能够匹配出多少对。
解题思路:
这道题是明显的二分匹配题目。有个强大的算法:匈牙利算法,确实很凶,这算法挺牛叉。
这道题属于单边匹配。
算法的大体过程:
先让图的左边去右边找匹配项,(右边可能有多个),暂时先找一个,然后再由左边的下一个项可是找,如果有刚刚好剩下的符合自己的项就添加,若不存在,则要调用递归函数path(macth[v]),然后上一项从新匹配,知道全部项都满足为止即为最大的匹配数。
感觉讲得不明不白吧。结合代码,还有左边的图,自己画一遍,就有思路了。试试看。
关于二分图的详细介绍:
发发牢骚:
这一次贡献了一个WA,因为我得nv=MAXV,所以path函数中的关于nv的,不能加“=”号,这是细节,分析下就出来了。以后要多用脑子想想。
代码:
#include<iostream> #include<stdio.h> using namespace std; const int MAXV=505; bool mat[MAXV][MAXV];//mat[u][v],从u到v是否连通 int nv,match[MAXV];//nv是结点数,match[v]表示右边的节点v的匹配项u(v是图的右边,v是图的左边,结合上面的那个图) int visited[MAXV];//访问过的点 int path(int u)//找u的匹配项 { int v; for(v=1;v<=nv;v++) { if(mat[u][v]&&!visited[v]) { visited[v]=1; if(match[v]==-1||path(match[v])) { match[v]=u; return 1; } } } return 0; } int max_match()//求最大匹配数 { int u,ans=0; memset(match,-1,sizeof(match)); for(u=1;u<=nv;u++) { memset(visited,0,sizeof(visited)); ans+=path(u); } return ans; } void init() { for(int i=0;i<MAXV;i++) for(int j=0;j<MAXV;j++) { mat[i][j]=0; } } int main(void) { int u,v,cas,girl,boy; while(scanf("%d",&cas),cas) { nv=MAXV-1;//注意减1,细节,上面的点都是<=nv的 scanf("%d%d",&girl,&boy);//女数,男数,这一句是没有用的 init(); for(int i=1;i<=cas;i++) { scanf("%d%d",&u,&v);//u 到 v连通,即女生u能够接受男生v mat[u][v]=1; } int count=max_match(); printf("%d\n",count); } return 0; } |