zoukankan      html  css  js  c++  java
  • 八中公司_二分图带权最大匹配模板题

    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个男生的期望值
    //附上蒟蒻代码
    #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;
    }
     
  • 相关阅读:
    《linux/unix设计思想》读后感
    webserver ZooKeeper Cluster
    OS + RedHat 6.3 x64 / sshd X11 /
    nGrinder SocketTest.groovy
    OS + Centos7.6 gdm / xmanager xstart
    OS + CentOS 7 / VirtualBox 6.0 / VMware-Workstation-Full-15.1.0
    浅谈MySQL Replication(复制)基本原理
    MySQL存储引擎比较
    explain SQL语句性能检测
    看看JavaScript中void(0)的含义
  • 原文地址:https://www.cnblogs.com/sbwll/p/12937176.html
Copyright © 2011-2022 走看看