poj 3189(多重匹配算法求解)

来源:互联网 发布:c语言 string 编辑:程序博客网 时间:2024/06/06 08:44

多重匹配的流解法:http://www.cppblog.com/MatoNo1/archive/2011/03/26/142766.aspx


多重匹配问题:二分图的最大匹配中左部图和右部图的顶点是一一对应的,然而在多重匹配中,左部图的的点可以和右部图的多个点匹配,但是右部图的顶点最多能和1个座部图进行匹配,即多对1或者一对多的关系


其中建图的思想和枚举思想和上一篇最大流解法一样 http://blog.csdn.net/hutu_mingbai/article/details/6724212

多重匹配见代码:


#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N = 1040;const int E = 40000;int g[N][25];int n;int e , head[N];int vlink[25];//vlink[i]表示点i+n和(1--n)的点中匹配的个数int link[25][N]; //link[i][j]表示和i+n匹配的点j个点bool vis[25];int C[25];struct node{int x, y,nxt,c;}edge[E];void addedge(int x,int y, int c){edge[e].x = x;edge[e].y=y;edge[e].c =c;edge[e].nxt=head[x];head[x]=e++;}int scan(int u){for(int i = head[u];i!=-1;i=edge[i].nxt){int v = edge[i].y;if(vis[v-n]==false){vis[v-n]=true;if(vlink[v-n]<C[v-n]){link[v-n][vlink[v-n]++]=u;return 1;}for(int j=0;j<vlink[v-n];j++)if(scan(link[v-n][j])){link[v-n][j]=u;return 1;}}}return 0;}int main (){int m;int i,j,k;while(scanf("%d%d",&n,&m)!=EOF){for(i=1;i<=n;i++)for(j=1;j<=m;j++)scanf("%d",&g[i][j]);//表示第i只牛喜爱程度为j的牛棚为g[i][j];for(i=1;i<=m;i++)scanf("%d",&C[i]);       //牛棚的容量int low=1,high=m;int result=0;while(low<=high) //枚举差值{int mid = (low+high)>>1;bool tag = false;for(i=1;i<=m-mid+1;i++){e =0;memset(head,-1,sizeof(head));for(j=1;j<=n;j++)for(k=i;k<=i+mid-1;k++)addedge(j,g[j][k]+n,1);//表示每条边只能匹配一次   memset(vlink,0,sizeof(vlink));   int ans = 0;   for(j=1;j<=n;j++)   {   memset(vis,0,sizeof(vis));   ans+=scan(j);   }   if(ans==n)   {   tag=true;   break;   }}if(tag){result=mid;high=mid-1;}else low=mid+1;}printf("%d\n",result);}return 0;}


原创粉丝点击