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;
}
时间: 2024-08-24 09:15:48

hdu 2853的相关文章

HDU 2853 &amp;&amp; HDU 3315

http://acm.hdu.edu.cn/showproblem.php?pid=2853 题意:给一个n-m二分图,边权用一个n*m的矩阵表示,给出初始匹配,求二分图完美匹配相比初始匹配改变了几条边以及改变的数值 这类题的主要思想是增加原配边的权值,但又不影响最后结果. 步骤1:观察顶点数,每条边乘一个大于顶点数的数v 步骤2:对于原配边,每边加1(注意步骤2可以保证km()/v的结果与原结果相同) 步骤3:求完美匹配,答案为res,改变的边数=n-res%v(res%v表示完美匹配中有多少

hdu 2853 Assignment 费用流

就是本来就给出了一个匹配,然后让你求一个权值最大的匹配,并且和初始匹配变动最小. #include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N=400; const int MAXE=20000000; const int inf=1<<30; int head[N],s,t,cnt,ans; int d[N],pre[N]; bool

HDU 2853 Assignment(KM最大匹配好题)

HDU 2853 Assignment 题目链接 题意:现在有N个部队和M个任务(M>=N),每个部队完成每个任务有一点的效率,效率越高越好.但是部队已经安排了一定的计划,这时需要我们尽量用最小的变动,使得所有部队效率之和最大.求最小变动的数目和变动后和变动前效率之差. 思路:对于如何保证改变最小,没思路,看了别人题解,恍然大悟,表示想法非常机智 试想,如果能让原来那些匹配边,比其他匹配出来总和相同的权值还大,对结果又不影响,那就简单了,这个看似不能做到,其实是可以做到的 数字最多选出50个,所

HDU 2853 最大匹配&amp;KM模板

http://acm.hdu.edu.cn/showproblem.php?pid=2853 这道题初看了没有思路,一直想的用网络流如何解决 参考了潘大神牌题解才懂的 最大匹配问题KM 还需要一些技巧来解决最小变动, 做法是:把原先的邻接矩阵每个数扩大k倍(k>n) 为了突出原先的选择,也就是同等情况下优先选择原来的方案 给原来的方案对应矩阵内的数据+1 那么 最终得出的最大匹配值/k=真实的最大匹配 最终得出的最大匹配值%k=原来的方案采用了几个 这里的KM留下来做模板 /* 二分图最佳匹配

HDU 2853 (KM最大匹配)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2853 题目大意:二分图匹配费用流.①最大匹配②最小原配变动 解题思路: 如果去掉第二个要求,那么就是裸KM. 然而加上第二个要求,那么就需要一种新的建图方式. 建图 对于输入矩阵,每一条边,cost扩大K倍($K=n+1$) 对于原配,每一条边cost在扩大K倍基础上+1 KM 统计cost时,直接把cost整除K,然后累加. 并且Hash一下原配边的变动情况. 扩大K倍的作用 准确来说,K倍是为了

hdu 2853 Assignment KM算法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2853 Last year a terrible earthquake attacked Sichuan province. About 300,000 PLA soldiers attended the rescue, also ALPCs. Our mission is to solve difficulty problems to optimization the assignment of t

Assignment (HDU 2853 最大权匹配KM)

Assignment Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1068    Accepted Submission(s): 551 Problem Description Last year a terrible earthquake attacked Sichuan province. About 300,000 PLA s

【图论】二分图匹配总结

二分图匹配总结 二分图匹配 1.二分图最大匹配.求两个集合内,每一个元素仅仅能用一次.两集合间存在一些匹配关系,求最大匹配多少对,利用匈牙利算法,对于每一个结点不断去找增广路去匹配 有几个重要性质: 1.最小点覆盖 = 最大匹配 2.最大独立集 = 总结点 - 最大匹配 模板: bool dfs(int u) { for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (vis[v]) continue; vis[v] = 1; i

[合集]国庆休闲补题

Hrbust - 1846 题意:序列每个格子允许放O和X,求长度为n的序列中至少存放m个连续的O的方案数 容斥+dp 设\(dp[i]\)为长度为\(i\)时的合法方案数 转移的个数来自于上一个状态的合法序列后面接上O和X,既\(dp[i-1]*2\) 也有可能来自于本来不合法的方案,转移后就合法了,那先固定一部分状态,因为转移后才合法,所以假定序列中[i-m+1,i]全部为O,那么前面就可以为所欲为,有\(2^{i-m}\)个状态,但\(2^{i-m}\)中会有合法方案的存在,因此需要减去已