二分图最大匹配

来源:互联网 发布:高仿巴宝莉风衣 知乎 编辑:程序博客网 时间:2024/05/01 11:50

                                                                                                                           月老的难题

          月老的难题,这一题是最大匹配问题,求最大匹配的常见方法有贪心(对出度的贪心),最大流算法(加个源点和汇点),在这是匈牙利算法(寻找增广路,每找到一个增广路,配对加一)

这道题我是用匈牙利算法写的(刚学的),下面我说下我对这个算法的理解,在做这题前,我没用过邻接表存过图,就因为我想写下邻接表,这道题一搁搁了好几天。今天第一次写时,还是老习惯用邻接矩阵(菜呀),写好之后,运行了一下,果断超时。那只好老老实实地去写邻接表吧,幸亏以前看过,看着一个同学的模板,写了下邻接表,存图的问题解决了,那接着就得解决匈牙利算法:匈牙利算法的核心就是寻找增广路,增广路,在我理解里它就是交错路径,而交错路径是什么呢?我是这样理解的,假如有两个集合A,B,A集合里一个点a1,去匹配B集合里的一点b1,而B集合里点b1早已和A中的a2匹配,如果B中有b2可以和a2匹配的,那么我们就让它与a2与b2匹配,如果b2在A中已经有匹配a3,那么我们再让a3去找匹配…………就这样直到找到一个未匹配的点,这就是一条交错路径,我就是这样理解的。

     用最大流和贪心去做这道题,代码我没写呢,只是从网上看了些东西,知道了这些思路,改天再写,代码有些凌乱。

 #include<stdio.h>#include<string.h>#define N 510#define K 10005struct{int head;}V[N];struct{int v,next;}E[K];int top,match[N],used[N];void Add_Edge(int u,int v){E[top].v=v;E[top].next=V[u].head;V[u].head=top++;}int DFS(int u){int i,v;for(i=V[u].head;i!=-1;i=E[i].next){v=E[i].v;if(!used[v]){used[v]=1;if(!match[v]||DFS(match[v])){match[v]=u;return 1;}}}return 0;}int main(){int t;scanf("%d",&t);while(t--){top=0;memset(match,0,sizeof(match));memset(V,-1,sizeof(V));int k,count,n,u,v,i;scanf("%d%d",&n,&k);for(i=0;i<k;i++){scanf("%d%d",&u,&v);Add_Edge(u,v);}count=0;for(i=1;i<=n;i++){memset(used,0,sizeof(used));if(DFS(i))count++;}printf("%d\n",count);}}