zoukankan      html  css  js  c++  java
  • UVA11383 Golden Tiger Claw KM算法

    题目链接:传送门

    分析

    这道题乍看上去没有思路,但是我们仔细一想就会发现这道题其实是一个二分图最大匹配的板子

    我们可以把这道题想象成将男生和女生之间两两配对,使他们的好感度最大

    我们把矩阵中的元素(a[x][y])看成女生(x)和男生(y)之间的好感度,跑一个KM算法

    因为KM算法会维护(ex_{}boy[x] + ex_{}girl[y]>=love[y][x]),所以最后的结果就是我们想要的

    注意有多组数据

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define hzoi 0
    const int maxn=505;
    int love[maxn][maxn];
    int ex_girl[maxn],ex_boy[maxn];
    bool vis_girl[maxn],vis_boy[maxn];
    int match[maxn],slack[maxn];
    int n;
    bool dfs(int girl){
        vis_girl[girl]=1;
        for(int boy=1;boy<=n;boy++){
            if(vis_boy[boy]) continue;
            int gap=ex_girl[girl]+ex_boy[boy]-love[girl][boy];
            if(gap==0){
                vis_boy[boy]=1;
                if(match[boy]==-1 || dfs(match[boy])){
                    match[boy]=girl;
                    return 1;
                }
            } else {
                slack[boy]=min(slack[boy],gap);
            }
        }
        return 0;
    }
    void KM(){
        memset(match,-1,sizeof(match));
        memset(ex_boy,0,sizeof(ex_boy));
        for(int i=1;i<=n;i++){
            ex_girl[i]=love[i][1];
            for(int j=2;j<=n;j++){
                ex_girl[i]=max(love[i][j],ex_girl[i]);
            }
        }
        for(int i=1;i<=n;i++){
            memset(slack,0x3f,sizeof(slack));
            while(1){
                memset(vis_boy,0,sizeof(vis_boy));
                memset(vis_girl,0,sizeof(vis_girl));
                if(dfs(i)) break;
                int d=0x3f3f3f3f;
                for(int j=1;j<=n;j++){
                    if(!vis_boy[j]) d=min(d,slack[j]);
                }
                for(int j=1;j<=n;j++){
                    if(vis_girl[j]) ex_girl[j]-=d;
                    if(vis_boy[j]) ex_boy[j]+=d;
                    else slack[j]-=d;
                }
            }
        }
    }
    int main(){
        while(scanf("%d",&n)!=EOF){
            memset(love,0,sizeof(love));
            memset(ex_girl,0,sizeof(ex_girl));
            memset(ex_boy,0,sizeof(ex_boy));
            memset(vis_girl,0,sizeof(vis_girl));
            memset(vis_boy,0,sizeof(vis_boy));
            memset(match,0x3f,sizeof(match));
            memset(slack,-1,sizeof(slack));
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    scanf("%d",&love[i][j]);
                }
            }
            KM();
            int ans=0;
            for(int i=1;i<=n;i++){
                if(i==1) printf("%d",ex_girl[i]);
                else printf(" %d",ex_girl[i]);
                ans+=ex_girl[i];
            }
            printf("
    ");
            for(int i=1;i<=n;i++){
                if(i==1) printf("%d",ex_boy[i]);
                else printf(" %d",ex_boy[i]);
                ans+=ex_boy[i];
            }
            printf("
    %d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    cocos2d学习笔录1
    js 动态切换视频
    Android之一个简单计算器源代码
    git-daemon的快捷搭建
    题目1384:二维数组中的查找
    [cocos2d-x]HelloWorldDemo
    ios开发者创建app应用开发授权文件 实战方法:
    一些小工具方法,能将容器转换成指定的数组类型有使用泛型
    Mockito文档-单元测试技术
    【UNIX网络编程】FIFO
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/12864244.html
Copyright © 2011-2022 走看看