Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
Last year a terrible earthquake attacked Sichuan province. About
300
,
000
300,000
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
N
N companies of troops and
M
M
M missions,
M
>
=
N
M>=N
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
E
i
j
E_{ij}
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
N
N and
M
.
M.
M.
N
N
N lines follow. Each contains
M
M
M integers, representing
E
i
j
E_{ij}
Eij. The next line contains
N
N
N integers. The first one represents the mission number that company
1
1
1 takes, and so on.
1
<
=
N
<
=
M
<
=
50
,
1
<
E
i
j
<
=
10000.
1<=N<=M<=50, 1<E_{ij}<=10000.
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
X
X and
Y
.
X
Y. X
Y.X represents the number of companies whose mission had been changed.
Y
Y
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
题意:
有
n
n
n个公司
m
m
m个工作,刚开始第
i
i
i个公司有对应的工作
b
e
l
o
n
g
[
i
]
belong[i]
belong[i],第
i
i
i个公司做第
j
j
j个工作的功效是
E
i
j
E_{ij}
Eij,重新分配工作,问最多增加多少功效;在功效最大的情况下,最少要调整几个公司的对应工作。
题解:
最大费用最大流,
i
,
j
i,j
i,j分别表示第
i
i
i个公司和第
j
j
j个工作,
i
−
>
j
+
n
i->j+n
i−>j+n流量为
1
1
1,费用为
E
i
j
∗
100
+
(
b
e
l
o
n
g
[
i
]
=
=
j
)
E_{ij}*100+(belong[i]==j)
Eij∗100+(belong[i]==j),然后做出的最大费用/100就是最大功效,最大费用%100就是剩下多少个公司的对应工作没变。
#include<bits/stdc++.h>
#define LiangJiaJun main
#define S 501
#define T 502
#define INF 1999122700
using namespace std;
int n,m,E[54][54];
struct edge{
int to,nt,w,c,from;
}e[100004];
int ne,h[504],from[504];
void add(int u,int v,int w,int c){
e[++ne].to=v;e[ne].w=w;
e[ne].c=c;e[ne].from=u;
e[ne].nt=h[u];h[u]=ne;
}
void INSERT(int u,int v,int w,int c){
add(u,v,w,c);
add(v,u,0,-c);
}
queue<int>q;
int dis[504],belong[54];
bool inq[504];
bool spfa(){
memset(inq,0,sizeof(inq));
for(int i=0;i<=T;i++)dis[i]=-INF;
dis[S]=0;inq[S]=1;
q.push(S);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=h[x];i;i=e[i].nt){
if(e[i].w&&dis[e[i].to]<dis[x]+e[i].c){
dis[e[i].to]=dis[x]+e[i].c;
from[e[i].to]=i;
if(!inq[e[i].to]){
inq[e[i].to]=1;
q.push(e[i].to);
}
}
}
inq[x]=0;
}
return (dis[T]!=-INF);
}
int mcf(){
int x=INF,ret=0;
for(int i=from[T];i;i=from[e[i].from])x=min(x,e[i].w);
for(int i=from[T];i;i=from[e[i].from]){
e[i].w-=x;e[i^1].w+=x;ret+=x*e[i].c;
}
return ret;
}
int w33ha(){
ne=1;
memset(h,0,sizeof(h));
memset(from,0,sizeof(from));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&E[i][j]);
int rag=0;
for(int i=1;i<=n;i++){
scanf("%d",&belong[i]);
rag+=E[i][belong[i]];
}
for(int i=1;i<=n;i++)INSERT(S,i,1,0);
for(int i=1;i<=m;i++)INSERT(i+n,T,1,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
INSERT(i,j+n,1,E[i][j]*100+(j==belong[i]));
int ans=0;
while(spfa())ans+=mcf();
printf("%d %d\n",n-(ans%100),ans/100-rag);
return 0;
}
int LiangJiaJun(){
while(scanf("%d%d",&n,&m)!=EOF)w33ha();
return 0;
}