首页 > 代码库 > 二分图最佳匹配,求最大权匹配或最小权匹配
二分图最佳匹配,求最大权匹配或最小权匹配
Beloved Sons http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1338
题意:国王有N个儿子,现在每个儿子结婚都能够获得一定的喜悦值,王子编号为1-N,有N个女孩的编号同样为1-N,每个王子心中都有心仪的女孩,现在问如果安排,能够使得题中给定的式子和最大。
分析:其实题目中那个开根号是个烟雾弹,只要关心喜悦值的平方即可。那么对王子和女孩之间构边,边权为喜悦值的平方,对于每一个王子虚拟出一个女孩边权为0,这样是为了所有的王子都能够有女孩可以配对,以便算法能够正确的执行。
求二分图最佳匹配,要求权值最大,lmatch返回一个最佳匹配。
1 #include<cstdio> 2 #include<cstring> 3 #define mt(a,b) memset(a,b,sizeof(a)) 4 const int inf=0x3f3f3f3f; 5 class Kuhn_Munkras { ///二分图最佳匹配O(ln*ln*rn)邻接阵 6 typedef int typec;///边权的类型 7 static const int MV=1024;///点的个数 8 int ln,rn,s[MV],t[MV],ll[MV],rr[MV],p,q,i,j,k; 9 typec mat[MV][MV];10 public:11 int lmatch[MV],rmatch[MV];12 void init(int tln,int trn) { ///传入ln左部点数,rn右部点数,要求ln<=rn,下标0开始13 ln=tln;14 rn=trn;15 for(i=0; i<ln; i++)16 for(j=0; j<rn; j++)17 mat[i][j]=-inf;18 }19 void add(int u,int v,typec w) {///最小权匹配可将权值取相反数20 mat[u][v]=w;21 }22 typec solve() {///返回最佳匹配值,-1表示无法匹配23 typec ret=0;24 for (i=0; i<ln; i++) {25 for (ll[i]=-inf,j=0; j<rn; j++)26 ll[i]=mat[i][j]>ll[i]?mat[i][j]:ll[i];27 if( ll[i] == -inf ) return -1;// 无法匹配!28 }29 for (i=0; i<rn; rr[i++]=0);30 mt(lmatch,-1);31 mt(rmatch,-1);32 for (i=0; i<ln; i++) {33 mt(t,-1);34 for (s[p=q=0]=i; p<=q&&lmatch[i]<0; p++)35 for (k=s[p],j=0; j<rn&&lmatch[i]<0; j++)36 if (ll[k]+rr[j]==mat[k][j]&&t[j]<0) {37 s[++q]=rmatch[j],t[j]=k;38 if (s[q]<0)39 for (p=j; p>=0; j=p)40 rmatch[j]=k=t[j],p=lmatch[k],lmatch[k]=j;41 }42 if (lmatch[i]<0) {43 for (i--,p=inf,k=0; k<=q; k++)44 for (j=0; j<rn; j++)45 if(t[j]<0&&ll[s[k]]+rr[j]-mat[s[k]][j]<p)46 p=ll[s[k]]+rr[j]-mat[s[k]][j];47 for (j=0; j<rn; rr[j]+=t[j]<0?0:p,j++);48 for (k=0; k<=q; ll[s[k++]]-=p);49 }50 }51 for (i=0; i<ln; i++) {52 if( lmatch[i] < 0 ) return -1;53 if( mat[i][lmatch[i]] <= -inf ) return -1;54 ret+=mat[i][lmatch[i]];55 }56 return ret;57 }58 } gx;59 int a[512];60 int main() {61 int t,n,m;62 while(~scanf("%d",&t)) {63 while(t--) {64 scanf("%d",&n);65 for(int i=0; i<n; i++) {66 scanf("%d",&a[i]);67 a[i]*=a[i];68 }69 gx.init(n,n<<1);70 for(int i=0,j; i<n; i++) {71 scanf("%d",&m);72 while(m--) {73 scanf("%d",&j);74 gx.add(i,j-1,a[i]);75 }76 gx.add(i,i+n,0);77 }78 int flag=gx.solve();79 for(int i=0; i<n; i++) {80 int ans=0;81 if(gx.lmatch[i]<n) {82 ans=gx.lmatch[i]+1;83 }84 printf("%d ",ans);85 }86 puts("");87 }88 }89 return 0;90 }
end
二分图最佳匹配,求最大权匹配或最小权匹配
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。