HDU 2853 Assignment 最大匹配+求最少改动的匹配数 之神奇建图
来源:互联网 发布:淘宝贷款15万可信么 编辑:程序博客网 时间:2024/06/03 14:52
点击打开链接
Assignment
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 756 Accepted Submission(s): 400
We have N companies of troops and M missions, M>=N. One company can get only one mission. One mission can be assigned to only one company. If company i takes mission j, we can get efficiency Eij.
We have a assignment plan already, and now we want to change some companies’ missions to make the total efficiency larger. And also we want to change as less companies as possible.
1<=N<=M<=50, 1<Eij<=10000.
Your program should process to the end of file.
3 32 1 33 2 41 26 22 1 32 31 2 31 2 31 2
2 261 2
题意是说有n个部队和m个任务,每个任务只能由一个部队完成,并且不同的部队完成不同的任务都有一个效率值。并且一开始已经给你哪个部队做哪个任务,让你求最少改动几个部队使得获得的效率值之差(最高的效率值-一开始给你的部队匹配任务的效率值)最高。
一开始直接求出最高效率值,然后减去已经给你的部队所匹配任务的效率值,第二问就求出来了。我用match数组将求得最大的效率值后的匹配和一开始它给你的进行比较,就得出改动的部队了。但是答案错了。题目要求的是最小的部队改动数,于是参考网上的题解:
因为我们要变动最小,所以对在原计划中的边要有一些特殊照顾,使得最优匹配时,尽量优先使用原计划的边,这样变化才能是最小的且不会影响原匹配。
根据这个思想,我们可以把每条边的权值扩大k倍,k要大于n。然后对原计划的边都+1。精华全在这里。我们来详细说明一下。
全部边都扩大了k倍,而且k比n大,这样,我们求出的最优匹配就是k倍的最大权值,只要除以k就可以得到最大权值。实现原计划的边加1,这样,在每次选择边时,这些变就 有了优势,就会优先选择这些边。假如原计划的h条边被选入了最优匹配中,这样,最优权值就是k倍的最大权值+k(原计划的每条边都+1)。但是k大于n的用意何在呢?我们发现假如原计划的边全部在匹配中,只会增加n,又n<k,所以除以k后不会影响最优匹配的最大权值之和,然后我们对k取余,就正好得到加入的原计划的边的个数。这时,我们只需要用总点数-加入的原计划的点数,就可以求得最小变动数了。
#include<stdio.h>#include<string.h>#define inf 0x3f3f3f#define M 57using namespace std;int g[M][M],match[M],slack[M],lx[M],ly[M],s[M];bool visx[M],visy[M];int n,m;bool dfs(int cur){ visx[cur]=true; for(int y=1;y<=m;y++) { if(visy[y])continue; int t=lx[cur]+ly[y]-g[cur][y]; if(t==0) { visy[y]=true; if(match[y]==-1||dfs(match[y])) { match[y]=cur; return true; } } else if(slack[y]>t) { slack[y]=t; } } return false;}int KM(){ memset(match,-1,sizeof(match)); memset(ly,0,sizeof(ly)); for(int i=1;i<=n;i++) { lx[i]=-inf; for(int j=1;j<=m;j++) if(g[i][j]>lx[i]) lx[i]=g[i][j]; } for(int x=1;x<=n;x++) { for(int i=1;i<=m;i++) slack[i]=inf; while(true) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(dfs(x))break; int d=inf; for(int i=1;i<=m;i++) if(!visy[i]&&d>slack[i]) d=slack[i]; for(int i=1;i<=n;i++) if(visx[i]) lx[i]-=d; for(int i=1;i<=m;i++) if(visy[i]) ly[i]+=d; else slack[i]-=d; } } int ans=0; for(int i=1;i<=m;i++) { if(match[i]==-1)continue; else { ans+=g[match[i]][i]; } } return ans;}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&g[i][j]); g[i][j]*=100; } int a,ans=0,count,tmp=0; for(int i=1;i<=n;i++) { scanf("%d",&a); ans+=g[i][a]; g[i][a]+=1; } count=KM(); printf("%d %d\n",n-count%100,count/100-ans/100); } return 0;}
- HDU 2853 Assignment 最大匹配+求最少改动的匹配数 之神奇建图
- HDU 2853 Assignment([好题] 求KM最大时,要求改动最少★★)
- ★ HDU 2853 求KM最大时,要求改动最少
- HDU-2853 Assignment【二分图最优匹配】
- HDU 2853 Assignment(二分图最优匹配)
- HDU 2853 Assignment(最佳二分图匹配)
- hdu 2853Assignment (二分图的最大权匹配)
- HDU 2853 Assignment(KM最大匹配好题)
- 二分图求最大匹配数,最完美匹配概念
- HDOJ 1845 Jimmy’s Assignment (求最大匹配数 匈牙利算法)
- 二分匹配求最大匹配数和最大匹配值
- ★ HDU 3315 求KM最大时,要求改动最少
- HDU1150 二分匹配 最少点覆盖=最大匹配数
- HDU-1498(二分匹配_求最大覆盖定点数)
- HDU 4160 Dolls 匈牙利算法求最大匹配数
- HDU-2444 二分图的判别和最大匹配数。
- HDU 2853 Assignment【二分图最优匹配+巧妙权值】
- Assignment (HDU 2853 最大权匹配KM)
- 为什么C++赋值运算符重载函数不能被继承?
- HDU--杭电--4506--小明系列故事——师兄帮帮忙--快速幂取模
- NoClassDefFoundError: org/apache/commons/pool/KeyedObjectPoolFactory
- UVALive 4643 Twenty Questions (压缩DP,4级)
- 传输层学习之六(SCTP)
- HDU 2853 Assignment 最大匹配+求最少改动的匹配数 之神奇建图
- 黑马程序员——Java基础语法(三)---数组
- CAsyncSocket::OnSend的触发条件
- SQL视图和多表连接
- .net Cookie原理与使用
- 一道困扰我许久的while循环题
- 链栈之C++实现
- iOS多线程GCD
- C#的几种格式转换