zoukankan      html  css  js  c++  java
  • [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
    ",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;
    }
    
  • 相关阅读:
    90.子类调用父类同名方法总结
    89.子类调用父类同名属性和方法
    88.子类调用父类同名属性和方法
    87.子类重写父类的同名属性和方法
    86.多继承
    85.单继承
    84.继承的概念
    day09
    83.魔法方法__del__()
    82.魔法方法__str__()
  • 原文地址:https://www.cnblogs.com/NLDQY/p/10342780.html
Copyright © 2011-2022 走看看