八中公司_二分图带权最大匹配模板题

Problem S: 八中公司

Description

小W在八中开了一个兼职中心。现在他手下有N个工人。每个工人有N个工作可以选择,于是每个人做每个工作的效率是不一样的。做为CEO的小W的任务就是给每个人分配一个工作,保证所有人效率之和是最大的。N<=200

Input

第一行给出数字N
接下来N行N列,代表每个人工作的效率。

Output

一个数字,代表最大效率之和

Sample Input

4
62 41 86 94
73 58 11 12
69 93 89 88
81 40 69 13

Sample Output

329

思路:
二分图带权最大匹配裸题
二分图带权最大匹配不会的看这里https://blog.csdn.net/x_y_q_/article/details/51927054
具体见代码
输入的w[i][j]就相当于第i个女生对第j个男生的期望值
//附上蒟蒻代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n,w[1001][1001];
 4 int lx[1001],ly[1001],matched[1001],slack[1001];
 5 bool s[1001],t[1001];
 6 bool match(int i) {//匈牙利算法
 7     s[i]=1; //第i个女生打上标记
 8     for(int j=1; j<=n; j++) {
 9         int cnt=lx[i]+ly[j]-w[i][j];//求出gap值
10         if(cnt==0&&!t[j]) { //如果gap值为0,且第J个男生在本轮没有被占用
11             t[j]=1;//打上标记
12             if(!matched[j]||match(matched[j]))
13                 //如果男生J从来没有被许配,或者被许配的对象可以向后调整的话
14             {
15                 matched[j]=i;
16                 //标记男生j被第i个女生占有
17                 return 1;
18             }
19         } else
20             slack[j]=min(slack[j],cnt);
21     }
22     return false;
23 }
24 void update() {
25     int a=INT_MAX;
26     for(int i=1; i<=n; i++)
27         if(!t[i])//没有被选到(匹配失败了)
28             a=min(a,slack[i]);//求出最少要减(加)的期望值
29     for(int i=1; i<=n; i++) {
30         if(s[i])lx[i]-=a;//女生降低期望值
31         if(t[i])ly[i]+=a;//男生增加期望值
32     }
33 }
34 void km() {
35     for(int i=1; i<=n; i++)
36         for(int j=1; j<=n; j++)
37             lx[i]=max(lx[i],w[i][j]);//求出女生最高期望值是多少
38     for(int i=1; i<=n; i++) {
39         memset(slack,0x3f,sizeof(slack));
40         while(1)
41             //整体采用贪心算法,保证每次能使一个女生匹配成功
42         {
43             memset(s,0,sizeof(s));
44             memset(t,0,sizeof(t));//注意每一轮s,t都要清空
45             if(match(i))
46                 break;
47             else
48                 //调整标顶值
49                 update();
50         }
51     }
52 }
53 int main() {
54     scanf("%d",&n);
55     for(int i=1; i<=n; i++)
56         for(int j=1; j<=n; j++)
57             scanf("%d",&w[i][j]);
58     km();
59     int ans=0;
60     for(int i=1; i<=n; i++)
61         ans+=lx[i]+ly[i];
62     printf("%d",ans);
63     return 0;
64 }
View Code

 

 
 
posted @ 2020-05-22 14:57  谁伴我流浪  阅读(211)  评论(2编辑  收藏  举报