assignment
assignment
Time limit: 2000/1000 MS (java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1593 Accepted Submission(s): 843
Problem Description
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 troops. The assignment is measure by efficiency, which is an integer, and the larger the better.
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.
Input
For each test case, the first line contains two numbers N and M. N lines follow. Each contains M integers, representing Eij. The next line contains N integers. The first one represents the mission number that company 1 takes, and so on.
1<=N<=M<=50, 1<Eij<=10000.
Your program should process to the end of file.
Output
For each the case print two integers X and Y. X represents the number of companies whose mission had been changed. Y represents the maximum total efficiency can be increased after changing.
Sample Input
3 3 2 1 3 3 2 4 1 26 2 2 1 3 2 3 1 2 3 1 2 3 1 2
Sample Output
2 26 1 2
Source
2009 Multi-University Training Contest 5 - Host by NUDT
Recommend
gaojie | We have carefully selected several similar problems for you: 2855 2854 2856 2857 2858
题解:
因为我们要变动最小,所以对在原计划中的边要有一些特殊照顾,使得最优匹配时,尽量优先 使用原计划的边,这样变化才能是最小的且不会影响原匹配。
根据这个思想,我们可以把每条边的权值扩大k倍,k要大于n。然后对原计划的边都+1。
全部边都扩大了k倍,而且k比n大,这样,我们求出的最优匹配就是k倍的最大权值,只要除以k就可以得到最大权值。实现原计划的边加1,这样,在每次选择边时,这些变就 有了优势,就会优先选择这些边。假如原计划的h条边被选入了最优匹配中,这样,最优权值就是k倍的最大权值+h(原计划的每条边都+1)。但是k大于n的用意何在呢?我们发现假如原计划的边全部在匹配中,只会增加n,又n小于k,所以除以k后不会影响最优匹配的最大权值之和,然后我们对k取余,就正好得到加入的原计划的边的个数。这时,我们只需要用总点数-加入的原计划的点数,就可以求得最小变动数了。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,eg[501],eb[501],a[501][501],visg[501],visb[501],ha[501],g[501];
int pd(int x){
int i,d;
visg[x]=1;
for(i=1;i<=m;i++){
if(visb[i])continue;
d=eg[x]+eb[i]-a[x][i];
if(!d){
visb[i]=1;
if(!g[i]||pd(g[i])){
g[i]=x;
return 1;
}
}
else ha[i]=min(ha[i],d);
}
return 0;
}
int KM(){
memset(g,0,sizeof(g));
memset(eb,0,sizeof(eb));
int i,j,d,ans=0;
for(i=1;i<=n;i++){
eg[i]=a[i][1];
for(j=2;j<=m;j++)eg[i]=max(eg[i],a[i][j]);
}
for(i=1;i<=n;i++){
memset(ha,60,sizeof(ha));
//printf("%d\n",ha[1]);
while(1){
memset(visg,0,sizeof(visg));
memset(visb,0,sizeof(visb));
if(pd(i))break;
d=1010580540;
for(j=1;j<=m;j++)
if(!visb[j])d=min(d,ha[j]);
for(j=1;j<=n;j++)if(visg[j])eg[j]-=d;
for(j=1;j<=m;j++){
if(visb[j])eb[j]+=d;
else ha[j]-=d;
}
}
}
for(i=1;i<=m;i++)ans+=a[g[i]][i];
return ans;
}
int main(){
int sum,ans,i,j,t;
while(~scanf("%d%d",&n,&m)){
for(i=1;i<=n;i++)
for(j=1;j<=m;j++){
scanf("%d",&a[i][j]);
a[i][j]*=100;
}
sum=0;
for(i=1;i<=n;i++){
scanf("%d",&t);
sum+=a[i][t];
a[i][t]++;
}
ans=KM();
printf("%d %d\n",n-ans%100,ans/100-sum/100);
}
}
相关阅读
多无人机对组网雷达的协同干扰 1. 引言 前段时间忙里偷闲,想找虐一下,于是做了一下201
CMD命令窗口在一些特殊情况时我们会用到,如PING下看网络通不通。在CMD窗口里运行命令如磁盘格式转换,在开始运行输入CMD回车后,CMD命
钉钉福卡红包答题95分为什么?很多网友参与钉钉福卡红包活动答题后钉钉福卡红包只有95分,哪一题答案不对呢?下面seo实验室小编为大
一直在忙项目,终于有时间重新来总结下css。 一组嵌套的盒子,子盒子和父盒子之间想设置上边距,不能用margin-top设置。因为子盒子
转载自 这些面试中的智力题,你都会了吗 1. 给一个瞎子52张扑克牌,并告诉他里面恰好有10张牌是正面朝上的。要求这个瞎子把牌分