zoukankan      html  css  js  c++  java
  • hdu 2853

      题意:

      有n个军队,m个任务;

      下面给出n*m的矩阵,表示每个军队做每个任务的效率;

      最后一行给出n个军队的原匹配任务;

      问最少改变多少个匹配关系使得效率最大,且输出最大效率值;

      这道题我当时看着真的没什么思路,然后查了波题解,觉得真的是个好题啊。

      他要的是在现有的匹配上改变次数少并且优的,那么我们怎么处理?

      意思就是原来给出的在某种程度上比其他的要更优, 那么我们同时扩大K倍,原来匹配的扩大K倍+1。

      那么再次匹配就得到想要的答案了!

    /*  gyt
           Live up to every day            */
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<string>
    #include<map>
    #include <time.h>
    #define PI acos(-1)
    using namespace std;
    typedef long long ll;
    typedef double db;
    const int maxn = 3000+10;
    const int maxm=5000+10;
    const int modd = 10000007;
    const int INF = 0x3f3f3f;
    const db eps = 1e-9;
    int lx[maxn], ly[maxn], vx[maxn], vy[maxn];
    int slack[maxn], match[maxn];
    int a[maxn][maxn];
    int n, m, nx, ny;
    
    int dfs(int u) {
        vx[u]=1;
        for (int i=1; i<=ny; i++) {
            if (vy[i])  continue;
            int t=lx[u]+ly[i]-a[u][i];
            if (t==0) {
                vy[i]=1;
                if (match[i]==-1||dfs(match[i])) {
                    match[i]=u;
                    return 1;
                }
            }
            else if(slack[i]>t) {
                slack[i]=t;
            }
        }
        return 0;
    }
    int KM() {
        memset(ly, 0, sizeof(ly));
        memset(match, -1, sizeof(match));
        memset(lx, -INF, sizeof(lx));
        for (int i=1; i<=nx; i++) {
            for (int j=1; j<=ny; j++) {
                lx[i]=max(lx[i], a[i][j]);
            }
        }
        for (int i=1; i<=nx; i++) {
            memset(slack, INF, sizeof(slack));
            while(1) {
                memset(vx, 0, sizeof(vx));
                memset(vy, 0, sizeof(vy));
                if (dfs(i))  break;
                int d=INF;
                for (int j=1; j<=ny; j++) {
                    if (!vy[j]&&slack[j]<d) {
                        d=slack[j];
                    }
                }
                for (int j=1; j<=nx; j++) {
                    if (vx[j])  lx[j]-=d;
                }
                for (int j=1; j<=ny; j++) {
                    if (vy[j])
                        ly[j]+=d;
                    else  slack[j]-=d;
                }
            }
        }
        int ans=0;
        for (int i=1; i<=ny; i++) {
            if (match[i]>-1&&a[match[i]][i]) {
                ans+=a[match[i]][i];
            }
        }
        return ans;
    }
    void solve() {
        while(scanf("%d%d", &n, &m)!=EOF) {
            nx=n, ny=m;
            for (int i=1; i<=n; i++) {
                for (int j=1; j<=m; j++) {
                    scanf("%d", &a[i][j]);
                    a[i][j]*=100;
                }
            }
            int sum=0;
            for (int i=1; i<=n; i++) {
                int t; scanf("%d", &t);
                sum+=a[i][t];
                a[i][t]++;
            }
            int hh=KM();
            int ans=hh/100-sum/100;
            printf("%d %d
    ", n-hh%100, ans);
        }
    }
    int main() {
        int t = 1;
        //freopen("in.txt", "r", stdin);
        //scanf("%d", &t);
        while(t--)
            solve();
        return 0;
    }
  • 相关阅读:
    HTML5程序设计--SVG
    visual studio 2012 Github
    排序算法--鸡尾酒排序
    排序算法--归并排序
    排序算法--冒泡排序
    排序算法---插入排序
    外语学习的真实方法及误区
    学习新东西的唯一方法
    如何做好一个面试官——之学习篇
    求职者和面试官如何做好电话面试
  • 原文地址:https://www.cnblogs.com/gggyt/p/7264937.html
Copyright © 2011-2022 走看看