poj 2195 最小费用最大流

来源:互联网 发布:86版西游记源码 编辑:程序博客网 时间:2024/06/11 19:54
#include "stdio.h"   //poj 2195 最小费用最大流#include "string.h"#include "queue"#include "math.h"using namespace std;#define N 210#define INF 0x3fffffffstruct 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\n",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];}}