描述 Description
后勤部队运来一批武器(机枪和盔甲)。你要把这些武器分配给手下的marine们(每人一部机枪,一套盔甲)。可是问题来了。。。这些武器的型号不相同(武器是由出价最低的承包商制造的),把一部m型的机枪和一套n型的盔甲分配给一个marine得到的不满意值为(m-n)^2(每个marine当然希望自己得到的武器是同一型号的)。
你的任务就是把a部机枪和b套盔甲分配给手下n个marine。使他们的不满意值之和最小。
输入格式 InputFormat
第一行:3 个正整数 n , a , b (1<=n<=a,b<=80)第二行:a 个数表示每部机枪的型号
第三行:b 个数表示每套盔甲的型号
0<=型号值<=10000
输出格式 OutputFormat
输出一个数:最小不满意值。样例输入 SampleInput [复制数据]
Sample 1: 2 3 3 9 10 20 0 10 11 Sample 2: 3 4 4 3 9 7 4 4 2 5 5
样例输出 SampleOutput [复制数据]
Sample 1: 2 Sample 2: 5
题解
第一眼看有点像二分图匹配,但是有限定人数。所以用费用流。
直接在所有机枪和所有防弹衣之间连上有向边,边的费用为(a[i]-b[j])^2,容量为1。再加上超级源点0和第一汇点T1,费用为0,容量为1。
最后再加一个第二汇点T2,超级汇和第二汇点相连,费用为0,容量为n,用来进行人数限制。
最后来一次最小费用最大流就可以了。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define inf 0x7fffffff
using namespace std;
int n,a,b,x[82],y[82],T1,T2,zz=1,head[201];
struct bian {int frm,to,v,nx,c;} e[50000];
int from[201],dis[201],q[201],ans;
bool pd[201];
void insert(int u,int v,int w,int z)
{
zz++; e[zz].frm=u; e[zz].to=v;
e[zz].v=w; e[zz].c=z; e[zz].nx=head[u]; head[u]=zz;
zz++; e[zz].frm=v; e[zz].to=u;
e[zz].v=0; e[zz].c=-z; e[zz].nx=head[v]; head[v]=zz;
}
void build()
{
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
insert(i,j+a,1,(x[i]-y[j])*(x[i]-y[j]));
for(int i=1;i<=a;i++) insert(0,i,1,0);
for(int i=1;i<=b;i++) insert(i+a,T1,1,0);
insert(T1,T2,n,0);
}
void init()
{
scanf("%d%d%d",&n,&a,&b);
for(int i=1;i<=a;i++) scanf("%d",&x[i]);
for(int j=1;j<=b;j++) scanf("%d",&y[j]);
T1=a+b+1; T2=T1+1;
}
bool spfa()
{
for(int i=0;i<=T2;i++) dis[i]=inf;
int t=0,w=1,i;
q[0]=dis[0]=0; pd[0]=1;
while(t!=w)
{int p=q[t]; t=(t+1)%200;
i=head[p];
while(i)
{if(e[i].v&&dis[e[i].to]>dis[p]+e[i].c)
{from[e[i].to]=i;
dis[e[i].to]=dis[p]+e[i].c;
if(!pd[e[i].to])
{q[w]=e[i].to; pd[e[i].to]=1; w=(w+1)%200;}
}
i=e[i].nx;
}
pd[p]=0;
}
if(dis[T2]==inf) return 0;
return 1;
}
void getf()
{
int i,xx=inf;
i=from[T2];
while(i)
{xx=min(e[i].v,xx); i=from[e[i].frm];}
i=from[T2];
while(i)
{e[i].v-=xx; e[i^1].v+=xx;
ans+=xx*e[i].c; i=from[e[i].frm];
}
}
void mcf()
{while(spfa()) getf();}
int main()
{
init(); build(); mcf();
printf("%d",ans);
return 0;
}