zoukankan      html  css  js  c++  java
  • uva11383 Golden Tiger Claw 深入理解km算法

    /**
    题目: uva11383 Golden Tiger Claw 深入理解km算法
    链接:https://vjudge.net/problem/UVA-11383
    题意:lv
    思路:lrj训练指南P351,少林决胜,理解km算法。求一个最大权匹配。
    
    */
    
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <queue>
    using namespace std;
    const int MAXN = 505;
    const int INF = 0x3f3f3f3f;
    
    int love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
    int ex_girl[MAXN];      // 每个妹子的期望值
    int ex_boy[MAXN];       // 每个男生的期望值
    bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
    bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
    int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
    int slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
    
    int N;//左侧顶点数=右侧顶点数=N;
    
    bool dfs(int girl)
    {
        vis_girl[girl] = true;
    
        for (int boy = 0; 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] = true;
                if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
                    match[boy] = girl;
                    return true;
                }
            } else {
                slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
            }
        }
    
        return false;
    }
    ///妹子在左边,男生在右边。
    int KM()
    {
        memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
        memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
    
        // 每个女生的初始期望值是与她相连的男生最大的好感度
        for (int i = 0; i < N; ++i) {
            ex_girl[i] = love[i][0];
            for (int j = 1; j < N; ++j) {
                ex_girl[i] = max(ex_girl[i], love[i][j]);
            }
        }
    
        // 尝试为每一个女生解决归宿问题
        for (int i = 0; i < N; ++i) {
    
            fill(slack, slack + N, INF);    // 因为要取最小值 初始化为无穷大
    
            while (1) {
                // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
    
                // 记录每轮匹配中男生女生是否被尝试匹配过
                memset(vis_girl, false, sizeof vis_girl);
                memset(vis_boy, false, sizeof vis_boy);
    
                if (dfs(i)) break;  // 找到归宿 退出
    
                // 如果不能找到 就降低期望值
                // 最小可降低的期望值
                int d = INF;
                for (int j = 0; j < N; ++j)
                    if (!vis_boy[j]) d = min(d, slack[j]);
    
                for (int j = 0; j < N; ++j) {
                    // 所有访问过的女生降低期望值
                    if (vis_girl[j]) ex_girl[j] -= d;
    
                    // 所有访问过的男生增加期望值
                    if (vis_boy[j]) ex_boy[j] += d;
                    // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
                    else slack[j] -= d;
                }
            }
        }
    
        // 匹配完成 求出所有配对的好感度的和
        int res = 0;
        for (int i = 0; i < N; ++i)
            res += love[ match[i] ][i];
    
        return res;
    }
    int main()
    {
        while (scanf("%d",&N)==1) {//N外部变量
            for(int i = 0; i < N; ++i)
                for(int j = 0; j < N; ++j){
                    scanf("%d",&love[i][j]);
                    love[i][j] = love[i][j];
                }
            int mis = KM();
            for(int i = 0; i < N; i++){
                if(i==N-1){
                    printf("%d
    ",ex_girl[i]);
                }else
                {
                    printf("%d ",ex_girl[i]);
                }
            }
            for(int i = 0; i < N; i++){
                if(i==N-1){
                    printf("%d
    ",ex_boy[i]);
                }else
                {
                    printf("%d ",ex_boy[i]);
                }
            }
    
            printf("%d
    ",mis);
        }
        return 0;
    }
  • 相关阅读:
    Windows server 2016 解决“无法完成域加入,原因是试图加入的域的SID与本计算机的SID相同。”
    Windows Server 2016 辅助域控制器搭建
    Windows Server 2016 主域控制器搭建
    Net Framework 4.7.2 覆盖 Net Framework 4.5 解决办法
    SQL SERVER 2012更改默认的端口号为1772
    Windows下彻底卸载删除SQL Serever2012
    在Windows Server2016中安装SQL Server2016
    SQL Server 创建索引
    C#控制台或应用程序中两个多个Main()方法的设置
    Icon cache rebuilding with Delphi(Delphi 清除Windows 图标缓存源代码)
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7206208.html
Copyright © 2011-2022 走看看