acdream 1227 Beloved Sons 二分匹配

来源:互联网 发布:vb.net cad插件 编辑:程序博客网 时间:2024/05/02 05:05

传送门:acdream 1227

        有个国王有n个儿子要找对象,现在恰好有n个妹子跟他们配对,每个人都有自己中意的一至多个妹子(像话么!!),如果配对到中意的妹子则会有满意度,问怎么配对能使得总的满意度最大,输出配对方案,假如配对对象不中意则输出0,否则输出妹子的编号


        红果果的最大权匹配,

        二分图,儿子一边,妹子一边,每个儿子向所有妹子建边,若是中意的妹子,边权赋为满意度,然后套用km模板求出匹配方案即可

/****************************************************** * File Name:   b.cpp * Author:      kojimai * Creater Time:2014年10月05日 星期日 12时05分42秒******************************************************///二分最大权匹配,并输出每个人的匹配对象,若匹配值为0,则输出0#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<iostream>using namespace std;#define FFF 405int n,ans[FFF],love[FFF],linkx[FFF];int len[FFF][FFF],sx[FFF],sy[FFF],lx[FFF],ly[FFF];bool bfs(int i){int j;sx[i] = 1;for(j = 1;j <= n;j++){if(!sy[j]&&lx[i] + ly[j] == len[i][j]){sy[j] = 1;if(!ans[j] || bfs(ans[j])){linkx[i] = j;ans[j] = i;return true;}}}return false;}void km(){int i,j,d,x;for(i = 1;i <= n;i++){lx[i] = -1;for(j = 1;j <= n;j++)lx[i] = max(lx[i],len[i][j]);}memset(ly,0,sizeof(ly));memset(ans,0,sizeof(ans));for(x = 1;x <= n;x++)  {while(1){memset(sx,0,sizeof(sx));memset(sy,0,sizeof(sy));if(bfs(x))break;d = 23333333;for(i = 1;i <= n;i++){if(sx[i])for(j = 1;j <= n;j++)if(!sy[j])d = min(d,lx[i]+ly[j]-len[i][j]);}for(i = 1;i <= n;i++)if(sx[i]) lx[i] -= d;for(j = 1;j <= n;j++)if(sy[j]) ly[j] += d;}}}int main(){int k,x;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&love[i]);memset(len,0,sizeof(len));for(int i=1;i<=n;i++){scanf("%d",&k);while(k--){scanf("%d",&x);len[i][x] = love[i];}}km();for(int i = 1;i <= n;i++){if(len[i][linkx[i]])printf("%d",linkx[i]);elseprintf("%d",0);if(i<n)printf(" ");elseprintf("\n");}return 0;}


0 0
原创粉丝点击