二分图最佳匹配,求最大权匹配或最小权匹配

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

时间: 2024-10-03 13:30:02

二分图最佳匹配,求最大权匹配或最小权匹配的相关文章

POJ 2195 二分图最小权匹配KM算法

本来是打算昨天晚上写的, 昨天网速渣的连CSDN都进不去,没办法 只能现在来写了 先写写对KM算法的理解,KM算法是对每个点设置一个顶标,只有当边长等于两边点的顶标之和的时候才进行增广,这样就能保证得到的一定是最大权匹配. 如果找不到匹配的时候就对交替路中X集合的顶标减少一个d Y集合的顶标增加一个d. 这样两个点都在交替路中的时候x[i]+y[i]的和不边 X在 Y不在的时候x[i]+y[i]减少,可能就会为图增加一对匹配. X不在Y在的时候x[i]+y[i]增加, 原来不在现在依然不在其中.

[ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receivesN orders for toys. The man

【POJ 2195】 Going Home(KM算法求最小权匹配)

[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20303   Accepted: 10297 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit ste

poj 2195 Going Home 二分图最小权匹配KM算法

题意: 有n个人要回到n间房子里,每间房子只允许一个人,求n个人要走的最小距离和. 分析: 裸的二分图最小权匹配,KM搞之. 代码: //poj 2195 //sep9 #include <iostream> using namespace std; const int maxN=128; char g[maxN][maxN]; int mx[maxN],my[maxN],hx[maxN],hy[maxN]; int w[maxN][maxN]; int lx[maxN],ly[maxN],l

ural 1076 KM求最小权匹配

贴模板~ KM算法引进了顶标函数,不断缩小这个顶标来让相等子图的可能范围扩大 #include<iostream> #include<cstring> //KM 复杂度O^3 using namespace std; const int N=200; int lx[N],ly[N];//顶标函数 int w[N][N];//图 bool vix[N],viy[N]; int linky[N];// int lack;//每次顶标函数扩大的增量 int n,m; bool find(

【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)

[POJ 2400] Supervisor, Supervisee(KM求最小权匹配) Supervisor, Supervisee Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2538   Accepted: 719 Description Suppose some supervisors each get to hire a new person for their department. There are N

poj3565Ants【最小权匹配】

大意: 左图为一个坐标轴上的点  其中黑点代表ants 白点代表apple 问怎样安排ants匹配apple才能使人一两条边不想交 分析: 如左图,我们假设a->d,b->c为一个最佳匹配  交点为e 那么ad+bc = ae+ ed + be + ec = (ae + ec) + (be + ed)  该值大于ac+bd 所以匹配为最佳匹配不成立 因此我们只要求出二分图的最小匹配就是结果了 但是wa了: wa的代码: 1 #include <iostream> 2 #includ

POJ 3686 The Windy&#39;s【最小权匹配(神建图啊)】

大意:有n个任务m个机器,告诉你n*m的矩阵表示每个任务在每个机器上完成需要的时间 问所有任务完成的总时间最少?(比如第一个任务在第一分钟完成第二个任务在第二分钟完成   则总时间为1 + 2 = 3 分析: 该题自己做的时候没有思路 后来在网上搜题解,感觉建图真是太厉害了 假设最优情况下,个个任务需要的时间分别为a1, a2, a3, ……,an 那么总时间t = n * a1 + (n - 1) * a2 + ……+ 2 * an - 1 + an 也就是说只需要考虑系数就可以了 我们先假设

poj2195 bfs+最小权匹配

题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费1美金,求所有人都进入房子的最小花费,这是典型的二分图带权匹配问题. 这题就是建图有点麻烦,但绝不抽象,直接用BFS遍历每个人到所有房子的距离,遍历出一个就拉一条人到房子有向边,建完图就是套模板了. 注意:KM算法是求最大权匹配的,要求最小权就要把所有边取相反数,最后结果再取相反数,但这只能是完美匹配,不完美匹配还要变一些. 1 #include<cstdio> 2 #include