[tyvj1982]武器分配
Description
后勤部队运来一批武器(机枪和盔甲)。你要把这些武器分配给手下的marine们(每人一部机枪,一套盔甲)。
可是问题来了。。。这些武器的型号不相同(武器是由出价最低的承包商制造的),把一部m型的机枪和一套n型的盔甲分配给一个marine得到的不满意值为(m-n)^2(每个marine当然希望自己得到的武器是同一型号的)。
你的任务就是把a部机枪和b套盔甲分配给手下n个marine。使他们的不满意值之和最小。
Input
第一行:3 个正整数 n , a , b (1<=n<=a,b<=80)
第二行:a 个数表示每部机枪的型号
第三行:b 个数表示每套盔甲的型号
0<=型号值<=10000
Output
输出一个数:最小不满意值。
Solution:
本题用费用流来写。
建模:首先,把每一个人与源点连起来 S -> person 容量:1 费用:0
把每一把枪都和所有的盔甲连起来,容量为1,费用为选择这两种的不满度
然后,再把每一件盔甲都与汇点相连,容量为1,费用为0
由于每一把枪和每一件盔甲都只能用一次,我们建立一个中转站tmp
把每个人和tmp相连,再把tmp和每一把枪相连,容量为1,费用为0
最后跑一遍费用流就行了
Code:
#include<bits/stdc++.h>
#define N 50001
#define inf 1926081700
using namespace std;
int n,a,b,cnt=1,tmp;
int S,T,head[N],gun[81];
struct Edge{int nxt,to,v,w;}edge[N];
void ins(int x,int y,int z,int w){
edge[++cnt].nxt=head[x];
edge[cnt].to=y;edge[cnt].v=z;
edge[cnt].w=w;head[x]=cnt;
}
namespace Network_Flow{
queue<int> q;
int delta,maxflow,mincost;
int vis[N],pre[N],dis[N];
int spfa(){
delta=inf;pre[T]=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=tmp;i++) dis[i]=inf;
q.push(S);vis[S]=1;dis[S]=0;
while(!q.empty()){
int x=q.front();q.pop();vis[x]=0;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(edge[i].v&&dis[x]+edge[i].w<dis[y]){
dis[y]=edge[i].w+dis[x];
delta=min(delta,edge[i].v);
pre[y]=i;if(!vis[y]) q.push(y),vis[y]=1;
}
}
}
return pre[T];
}
void update(){
int x=T;
while(x!=S){
int u=pre[x];
edge[u].v-=delta;
edge[u^1].v+=delta;
x=edge[u^1].to;
}
maxflow+=delta;mincost+=dis[T];
}
void Edmonds_Karp(){
while(spfa()) update();
printf("%d\n",mincost);
}
}
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main(){
n=read(),a=read(),b=read();
S=n+a+b+1,T=S+1,tmp=T+1;
using namespace Network_Flow;
for(int i=1;i<=n;i++)
ins(S,i,1,0),ins(i,S,0,0);
for(int i=1;i<=n;i++)
ins(i,tmp,1,0),ins(tmp,i,0,0);
for(int i=1;i<=a;i++){
gun[i]=read();
ins(tmp,i+n,1,0);
ins(i+n,tmp,0,0);
}
for(int i=1;i<=b;i++){
int x=read();
for(int j=1;j<=a;j++){
int y=x-gun[j];y*=y;
ins(j+n,i+a+n,1,y);
ins(i+a+n,j+n,0,-y);
}
ins(i+a+n,T,1,0);
ins(T,i+a+n,0,0);
}
Edmonds_Karp();
return 0;
}