zoukankan      html  css  js  c++  java
  • poj 2195 最小费用最大流

    #include "stdio.h"   //poj 2195 最小费用最大流
    #include "string.h"
    #include "queue"
    #include "math.h"
    using namespace std;
    
    #define N 210
    #define INF 0x3fffffff
    
    struct node{
    	int u,v,w,k;
    	int next;
    }edge[4*N*N];
    
    struct point{
    	int x,y;
    }people[N],house[N];
    
    bool mark[N];
    int start,end;
    int n,ans,idx;
    int dis[N],route[N],head[N];
    
    void init();
    bool SPFA();
    void EK();
    void adde(int u,int v,int w,int k);
    void addedge(int u,int v,int w,int k);
    
    int main()
    {
    	int L,D;
    	int i,j;
    	int x,y,w;
    	char map[105][105];
    	while(scanf("%d%d",&L,&D),L&&D)
    	{
    		for(i=1;i<=L;i++)
    			scanf("%s",map[i]+1);
    		x=y=0;
    		for(i=1;i<=L;i++)
    		{
    			for(j=1;j<=D;j++)
    			{
    				if(map[i][j]=='m'){	people[x].x = i;	people[x].y = j;  x++;}
    				if(map[i][j]=='H'){ house[y].x = i;		house[y].y = j;	  y++;}
    			}
    		}
    		init();
    		n=x;
    		start = 0;   //起点
    		end = n+n+1;   //终点
    		for(i=1;i<=n;i++)
    			adde(start,i,0,1); //1~n每个点代表人
    		for(i=1;i<=n;i++)
    		{
    			for(j=1;j<=n;j++)  //n+1~n+n每个点代表house
    			{
    				w = abs(people[i-1].x-house[j-1].x)+abs(people[i-1].y-house[j-1].y);
    				adde(i,j+n,w,1);
    			}
    		}
    		for(i=1;i<=n;i++)
    			adde(i+n,end,0,1);
    		while(SPFA())
    			EK();
    		printf("%d
    ",ans);
    	}
    	return 0;
    }	
    
    void init()
    {
    	ans = 0;
    	idx = 0;
    	memset(head,-1,sizeof(head));
    }
    
    void adde(int u,int v,int w,int k)
    {
    	addedge(u,v,w,k);
    	addedge(v,u,-w,0);
    }
    
    void addedge(int u,int v,int w,int k)
    {
    	edge[idx].u = u;
    	edge[idx].v = v;
    	edge[idx].w = w;
    	edge[idx].k = k;
    	edge[idx].next = head[u];
    	head[u] = idx;
    	idx++;
    }
    
    bool SPFA()
    {
    	int i;
    	int x,y;
    	memset(route,-1,sizeof(route));
    	memset(mark,false,sizeof(mark));
    	for(i=0;i<N;i++)	dis[i] = INF;
    	dis[0] = 0;
    	queue<int> q;
    	q.push(start);
    	mark[start] = true;
    	while(!q.empty())
    	{
    		x = q.front();
    		q.pop();
    		mark[x] = false;
    		for(i=head[x];i!=-1;i=edge[i].next)
    		{
    			y = edge[i].v;
    			if(edge[i].k && dis[y]>dis[x]+edge[i].w)
    			{
    				route[y] = i;
    				dis[y] = dis[x] + edge[i].w;
    				if(mark[y]==false)
    				{
    					mark[y] = true;
    					q.push(y);
    				}
    			}
    		}	
    	}
    	route[0] = -1;
    	if(route[end]==-1) return false;
    	return true;
    }
    
    void EK()
    {
    	int x,y;
    	y = route[end];
    	while(y!=-1)
    	{
    		x = y^1;
    		ans+=edge[y].w;
    		edge[y].k--;
    		edge[x].k++;
    		y = route[edge[y].u];
    	}
    }

  • 相关阅读:
    大话数据结构笔记
    zsh安装教程
    Matlab安装教程
    7-16 插入排序还是归并排序 (25 分)
    7-14 插入排序还是堆排序 (25 分)
    7-14 二叉搜索树的最近公共祖先 (30 分)
    7-11 笛卡尔树 (25 分)
    中缀转换为后缀和前缀
    7-15 水果忍者 (30 分)
    兔子的区间密码(思维)
  • 原文地址:https://www.cnblogs.com/ruo-yu/p/4411994.html
Copyright © 2011-2022 走看看