zoukankan      html  css  js  c++  java
  • Poj 2195 Going Home

    题目链接:ヾ(≧∇≦*)ゝ

    题意:有n*m的矩阵,H表示这个点是一个房子,m表示这个点是一个人,现在每一个人需要走入一个房间,已经知道的是
    认得数目和房子的个数一定是相同的,现在问这些人都回到一个房间所走的总的步数最小

    Solution:

    (2le nle100,2le mle100),费用流

    把所有的人和房子连边,容量为1,费用为需要的步数

    把源点与人连边,容量为1,费用为0,汇点与房子连边,容量为1,费用为0

    需要解释的是为什么汇点与房子连的边容量为1,这是因为每个房子只能住一个人

    最后一遍费用流得出答案。本题有多组数据,读入到0结束。

    Code:

    #include<queue>
    #include<cstdio>
    #include<ctype.h>
    #include<cstring>
    #include<algorithm>
    #define N 50001
    #define inf 1926081700
    using namespace std;
    typedef pair<int,int> pii;
    int n,m,cnt=1,t;
    int S,T,head[N],per[N];
    char mp[101][101];
    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<=T;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(){
            mincost=maxflow=0;
    		while(spfa()) update();
    		printf("%d
    ",mincost);
    	}
    }
    void format(){
        cnt=1;t=0;
        memset(head,0,sizeof(head));
        memset(edge,0,sizeof(edge));
    }
    int num(int i,int j){return (i-1)*m+j;}
    pii pos(int x){return make_pair(x/m+(x%m!=0),(x%m==0)?m:x%m);}
    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(){
    	using namespace Network_Flow;
    	begin:n=read();m=read();
        if(n==0||m==0) return 0;
        S=n*m+1;T=S+1;format();
        for(int i=1;i<=n;i++)
            scanf("%s",mp[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='m'){
                    int x=num(i,j);
                    per[++t]=num(i,j);
                    ins(S,x,1,0);ins(x,S,0,0);
                }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='H'){
                    int x=num(i,j);
                    for(int k=1;k<=t;k++){
                        pii tmp=pos(per[k]);
                        int w=abs(tmp.first-i)+abs(tmp.second-j);
                        ins(per[k],x,1,w);ins(x,per[k],0,-w);
                    }
                    ins(x,T,1,0);ins(T,x,0,0);
                }
        Edmonds_Karp();goto begin;
    }
    
  • 相关阅读:
    Google Shell Style Guide
    50 Must-have plugins for extending Twitter Bootstrap
    HTTP 请求头中的 X-Forwarded-For
    如何让 PowerPoint 幻灯片「高大上」?
    数据挖掘系列(1)关联规则挖掘基本概念与Aprior算法
    关于大型网站技术演进的思考(三)--存储的瓶颈(3)
    基于 Nginx XSendfile + SpringMVC 进行文件下载
    如何成为全栈工程师?
    Sqlserver通过列名查表名
    animate
  • 原文地址:https://www.cnblogs.com/NLDQY/p/10343168.html
Copyright © 2011-2022 走看看