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

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
二分图带权最大匹配裸题
输入的a[i]就相当于第i个女生对n个男生的期望值
//附上蒟蒻代码
#include <bits/stdc++.h>
using namespace std;
int n,w[1001][1001];
int lx[1001],ly[1001],matched[1001],slack[1001];
bool s[1001],t[1001];
bool match(int i) {//匈牙利算法 
    s[i]=1; //第i个女生打上标记
    for(int j=1; j<=n; j++)
    {
        int cnt=lx[i]+ly[j]-w[i][j];//求出gap值
        if(cnt==0&&!t[j])//如果gap值为0,且第J个男生在本轮没有被占用
        {
            t[j]=1;//打上标记
            if(!matched[j]||match(matched[j]))
                //如果男生J从来没有被许配,或者被许配的对象可以向后调整的话
            {
                matched[j]=i;
                //标记男生j被第i个女生占有
                return 1;
            }
        } 
        else
            slack[j]=min(slack[j],cnt);
    }
    return false;
}
void update() {
    int a=INT_MAX;
    for(int i=1; i<=n; i++)
        if(!t[i])//没有被选到(匹配失败了) 
            a=min(a,slack[i]);//求出最少要减(加)的期望值 
    for(int i=1; i<=n; i++)
    {
        if(s[i])lx[i]-=a;//女生降低期望值 
        if(t[i])ly[i]+=a;//男生增加期望值 
    }
}
void km() {
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            lx[i]=max(lx[i],w[i][j]);//求出女生最高期望值是多少 
    for(int i=1; i<=n; i++)
    {
        memset(slack,0x3f,sizeof(slack));
        while(1)
            //整体采用贪心算法,保证每次能使一个女生匹配成功
        {
            memset(s,0,sizeof(s));
            memset(t,0,sizeof(t));//注意每一轮s,t都要清空 
            if(match(i))
                break;
            else
                //调整标顶值
                update();
        }
    }
}
int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    for(int j=1; j<=n; j++)
        scanf("%d",&w[i][j]);
    km();
    int ans=0;
    for(int i=1; i<=n; i++)
        ans+=lx[i]+ly[i];
    printf("%d",ans);
    return 0;
}
 

猜你喜欢

转载自www.cnblogs.com/sbwll/p/12937176.html