hdu 2853

Posted gggyt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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", n-hh%100, ans);
    }
}
int main() {
    int t = 1;
    //freopen("in.txt", "r", stdin);
    //scanf("%d", &t);
    while(t--)
        solve();
    return 0;
}

 

以上是关于hdu 2853的主要内容,如果未能解决你的问题,请参考以下文章

hdu 2853

KM算法的应用

HDU3732 背包DP

洛谷P2853 [USACO06DEC]Cow Picnic S 题解

洛谷P2853 [USACO06DEC]Cow Picnic S 题解

P2853 [USACO06DEC]牛的野餐Cow Picnic