• 1047


    http://www.ifrog.cc/acm/problem/1047

    思路很简单,跑一发floyd,然后再用km。

    但是问题来了,这个有可能n != m。那怎么办?

    其实可以补上一些不存在的点。来使得n = m。他们的权值就设置为0就好了。意思就是这些人的搭配,是对答案没有贡献的。注意不能设置为-inf。因为补上的那些点也是必须要选人的,只不过他们选了人,相当于没选而已(权值不存在。)如果设置为-inf的那些,那么他们就会把答案改了。

    还有一个小trick的就是,一开始,我是把本来地图上的-1的那些点,更改为inf的,inf表示不连通,那么直接floyd就可以了不用特判那么多。那么问题又来了。如果跑了floyd后,还是不连通,那怎么办?他们的权值可是inf啊。组成新图的时候,同时也是需要把他们的权值设置为0的,也就是相当于没选。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 1e2 + 20;
    int e[maxn][maxn];
    int TE[2 * maxn][2 * maxn];
    int match[maxn];//match[col] = row
    int vx[maxn],vy[maxn];
    int fx[maxn],fy[maxn];
    int n, m;
    int dfs (int u) {
        vx[u]=1;
        int i;
        for (i=1; i<=m; i++) { //筛选n个 导航员 col的值
            if (vy[i]==0&&fx[u]+fy[i]==e[u][i]) {
                vy[i]=1;
                if (match[i]==0||dfs(match[i])) {
                    match[i]=u;// match[col]=row;
                    return 1;//搭配成功
                }
            }
        }
        return 0;//我找不到啊,后面,就会执行km
    }
    void do_km() { //
        int i,j;
        int d=inf;
        for (i=1; i<=n; i++) { //遍历每一个驾驶员 row的值
            if (vx[i]==1) {
                for (j=1; j<=m; j++) { //对他进行遍历导航员 col的值
                    if (!vy[j]) {
                        if (d>(fx[i]+fy[j]-e[i][j])) {
                            d=fx[i]+fy[j]-e[i][j];
                        }
                    }
                }
            }
        }
        for (i=1; i<=n; i++) {
            if (vx[i]==1) {
                fx[i] -= d;
                vx[i]=0;//请0
            }
            if (vy[i]==1) { //
                fy[i] += d;
                vy[i]=0;//情0
            }
        }
        return ;
    }
    int anskm() {
        memset (vx,0,sizeof(vx));
        memset (vy,0,sizeof(vy));
        memset (fx,0,sizeof(fx));
        memset (fy,0,sizeof(fy));
        memset (match,0,sizeof(match));
        //km算法的一部分,先初始化fx,fy
        for (int i=1; i<=n; i++) { //遍历每一个驾驶员 row的值
            fy[i]=0;
            fx[i]= -inf;//无穷小
            for (int j=1; j<=m; j++) { //遍历每一个导航员 col的值
                if (fx[i]<e[i][j]) { //默契值
                    fx[i]=e[i][j];
                }
            }
        }
        for (int i=1; i<=n; i++) { //遍历每一个驾驶员 row的值
            memset (vx,0,sizeof(vx));
            memset (vy,0,sizeof(vy));
            while (!dfs(i)) {//如果他找不到搭配,就实现km算法
                do_km();//km完后,还是会对这个想插入的节点进行dfs的,因为他还没搭配嘛
            }
    //        if (t == m) break;
        }
        int ans=0;
        for (int i=1; i<=m; i++) //遍历导航员,col的值
            ans += e[match[i]][i];//输入的row是驾驶员,col是导航员
        //match[i]:导航员i和驾驶员match[i]搭配了              match[col]=row;
        return ans;
    }
    
    void work() {
        memset(TE, 0, sizeof TE);
        memset(e, 0, sizeof e);
        cin >> n >> m;
        for (int i = 1; i <= n + m; ++i) {
            for (int j = 1; j <= n + m; ++j) {
                cin >> TE[i][j];
                if (TE[i][j] == -1) TE[i][j] = inf;
            }
        }
        for (int k = 1; k <= n + m; ++k) {
            for (int i = 1; i <= n + m; ++i) {
                for (int j = 1; j <= n + m; ++j) {
                    if (TE[i][j] > TE[i][k] + TE[k][j]) {
                        TE[i][j] = TE[i][k] + TE[k][j];
                    }
                }
            }
        }
    //    for (int i = 1; i <= n + m; ++i) {
    //        for (int j = 1; j <= n + m; ++j) {
    //            cout << TE[i][j] << " ";
    //        }
    //        cout << endl;
    //    }
    //    cout << endl;
    
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                e[i][j] = TE[i][n + j];
                if (e[i][j] == inf) {
                    e[i][j] = 0; //不联通,要用0代替
                }
            }
        }
        if (n > m) {
            for (int i = 1; i <= n; ++i) {
                for (int j = m + 1; j <= n; ++j) {
                    e[i][j] = 0;
                }
            }
            m = n;
        } else if (n < m) {
            for (int i = n + 1; i <= m; ++i) {
                for (int j = 1; j <= m; ++j) {
                    e[i][j] = 0;
                }
            }
            n = m;
        }
        cout << anskm() << endl;
    }
    int main() {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        IOS;
        int t;
        cin >> t;
        while (t--) work();
        return 0;
    }
  • 相关阅读:
    批量 kill mysql 线程
    ansible playbook实践(三)-yaml文件写法
    ansible playbook实践(二)-基础相关命令
    ansible playbook实践(一)-基础环境安装
    rsync源目录写法的一点小细节
    python threading queue模块中join setDaemon及task_done的使用方法及示例
    python多线程限制并发数示例
    完全总结bash中的条件判断test [ [[ 使用
    CHECK MEMBER TYPE
    C++14 make code cleaner
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6034739.html
Copyright © 2020-2023  润新知