zoukankan      html  css  js  c++  java
  • hdu1533 费用流模板

    Going Home

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 6114    Accepted Submission(s): 3211


    Problem Description
    On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man. 

    Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point. 

    You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.
     
    Input
    There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.
     
    Output
    For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay. 
     
    Sample Input
    2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
     
    Sample Output
    2 10 28
     
    大意:将两个点配对的花费为其曼哈顿距离,问将每个H与m配对的最小花费。
     
     
     
     
     
     
     
    题解:建二分图,带权匹配(KM暂时不会)。
    一切皆可网络流,也可以用费用流写,这题就当存个模板了。
     
    /*
    Welcome Hacking
    Wish You High Rating
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<ctime>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<string>
    using namespace std;
    int read(){
        int xx=0,ff=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){xx=(xx<<3)+(xx<<1)+ch-'0';ch=getchar();}
        return xx*ff;
    }
    const int maxlongint=(1LL<<31)-1;
    inline int myabs(int xx)
    {if(xx<0)return -xx;return xx;}
    inline int mymin(int xx,int yy)
    {if(xx>yy)return yy;return xx;}
    inline int mymax(int xx,int yy)
    {if(xx>yy)return xx;return yy;}
    int N,M,st,en;
    int s1[110],s2[110],tp1,tp2,ans;
    inline int get_id(int xx,int yy)
    {return (xx-1)*M+yy;}
    inline int get_dis(int id1,int id2){
    	int sx=id1/M,sy=id1%M,fx=id2/M,fy=id2%M;
    	if(!sy)
    		sx--,sy=M;
    	if(!fy)
    		fx--,fy=M;
    	return myabs(sx-fx)+myabs(sy-fy);
    }
    int lin[210],len;
    struct edge{
    	int y,next,v,f;
    }e[200010];
    inline void insert(int xx,int yy,int ff,int vv){
    	e[++len].next=lin[xx];
    	lin[xx]=len;
    	e[len].y=yy;
    	e[len].v=vv;
    	e[len].f=ff;
    }
    inline void ins(int xx,int yy,int ff,int vv)
    {insert(xx,yy,ff,vv),insert(yy,xx,0,-vv);}
    void build(){
    	st=tp1+tp2+1,en=st+1;
    	memset(lin,0,sizeof(lin));len=0;
    	for(int i=1;i<=tp1;i++)
    		for(int j=1;j<=tp2;j++)
    			ins(i,j+tp1,1,get_dis(s1[i],s2[j]));
    	for(int i=1;i<=tp1;i++)
    		ins(st,i,1,0);
    	for(int j=1;j<=tp2;j++)
    		ins(j+tp1,en,1,0);
    }
    int q[1000010],head,tail,dis[210],Prev[210],useedge[210];
    bool vis[210];
    bool SPFA(){
    	memset(vis,0,sizeof(vis));
    	memset(dis,10,sizeof(dis));
    	head=tail=0;
    	q[head]=st;
    	vis[q[head]]=1;
    	dis[q[head]]=0;
    	for(;head<=tail;head++){
    		vis[q[head]]=0;
    		for(int i=lin[q[head]];i;i=e[i].next)
    			if(e[i].f)
    				if(dis[e[i].y]>dis[q[head]]+e[i].v){
    					dis[e[i].y]=dis[q[head]]+e[i].v;
    					if(!vis[e[i].y]){
    						vis[e[i].y]=1;
    						q[++tail]=e[i].y;
    					}
    					Prev[e[i].y]=q[head];
    					useedge[e[i].y]=i;
    				}
    	}
    	//printf("#%d#
    ",dis[en]);
    	return dis[en]!=dis[0];
    }
    void agu(){
    	int add=maxlongint; 
    	for(int i=en;i!=st;i=Prev[i]){
    		add=mymin(add,e[useedge[i]].f);
    	}
    	for(int i=en;i!=st;i=Prev[i]){
    		e[useedge[i]].f-=add;
    		if(useedge[i]&1)
    			e[useedge[i]+1].f+=add;
    		else
    			e[useedge[i]-1].f+=add;
    		ans+=add*e[useedge[i]].v;
    	}
    }
    void cost_flow(){
    	ans=0;
    	while(SPFA())
    		agu();
    	printf("%d
    ",ans);
    }
    int main(){
    	//freopen("in","r",stdin);
    	//freopen("out","w",stdout);
    	while(1){
    		N=read(),M=read();
    		if((!N)&&(!M))
    			break;
    		tp1=tp2=0;
    		char tmp;
    		for(int i=1;i<=N;i++)
    			for(int j=1;j<=M;j++){
    				tmp=getchar();
    				while(tmp==10||tmp==32)
    					tmp=getchar();
    				if(tmp=='H')
    					s1[++tp1]=get_id(i,j);
    				else if(tmp=='m')
    					s2[++tp2]=get_id(i,j);
    			}
    		build();
    		cost_flow();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Delphi的 Format格式化函数
    Delphi的Trim函数
    Delphi容器类之---Tlist,TStringlist,THashedStringlist的效率比较
    Delphi容器类之---TOrderedList、TStack、TQueue、TObjectStack、TObjectQueue
    Delphi容器类之---TList、TObjectList、TComponentList、TClassList
    Delphi的分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同
    Delphi容器类之---TList、TStringList、TObjectList,以及一个例程的代码分析
    Linux C编程学习6---字符串处理、数据转换
    Linux C编程学习之开发工具3---多文件项目管理、Makefile、一个通用的Makefile
    Linux C编程学习之开发工具2---GDB调试器
  • 原文地址:https://www.cnblogs.com/lzhAFO/p/8149638.html
Copyright © 2011-2022 走看看