首页 > 代码库 > POJ2195:Going Home(费用流入门)

POJ2195:Going Home(费用流入门)

http://poj.org/problem?id=2195

#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <queue>#include <math.h>#define inf 0x3f3f3f3fusing namespace std;struct node1//记录h或者m的坐标{    int x,y;} a[402],b[402];struct node{    int x,y,c,w;    int next;} eg[600001];int n,m,tt,head[10001],v[10001],dis[10001],pre[10001],s,t;char map[102][102];void init(){    tt=0;    memset(head,-1,sizeof(head));    s=0;    t=n*m+1;}void add(int xx,int yy,int cc,int ww){    eg[tt].x=xx;    eg[tt].y=yy;    eg[tt].c=cc;    eg[tt].w=ww;    eg[tt].next=head[xx];    head[xx]=tt++;    eg[tt].x=yy;    eg[tt].y=xx;    eg[tt].c=0;    eg[tt].w=-ww;    eg[tt].next=head[yy];    head[yy]=tt++;}int spfa(int s,int t){    queue<int>q;    for(int i=0; i<=t; i++)    {        v[i]=0;        dis[i]=inf;        pre[i]=-1;    }    v[s]=1;    dis[s]=0;    q.push(s);    while(!q.empty())    {        int ff=q.front();        q.pop();        v[ff]=0;        for(int i=head[ff]; i!=-1; i=eg[i].next)        {            int w1=eg[i].y;            if(eg[i].c&&dis[w1]>dis[ff]+eg[i].w)            {                dis[w1]=dis[ff]+eg[i].w;                pre[w1]=i;//用边表建图存储其信息                if(!v[w1])                {                    v[w1]=1;                    q.push(w1);                }            }        }    }    if(dis[t]==inf)    {        return 0;    }    return 1;}void KM(int s,int t){    int min1,ans=0;    while(spfa(s,t)==1)    {        min1=inf;        for(int i=pre[t]; i!=-1; i=pre[eg[i].x])        {            if(min1>=eg[i].c)            {                min1=eg[i].c;            }        }        for(int i=pre[t]; i!=-1; i=pre[eg[i].x])        {            eg[i].c-=min1;            eg[i+1].c+=min1;        }        ans+=min1*dis[t];    }    printf("%d\n",ans);    return ;}int main(){    int t1,t2;    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0) break;        init();        t1=0;        t2=0;        for(int i=1; i<=n; i++)        {            scanf("%s",map[i]+1);//因为要创建超级源点,所以从一比较好计算            for(int j=1; j<=m; j++)            {                int l=(i-1)*m+j;//以点建图                if(map[i][j]==m)                {                    add(s,l,1,0);                    a[t1].x=i;                    a[t1++].y=j;                }                else if(map[i][j]==H)                {                    add(l,t,1,0);                    b[t2].x=i;                    b[t2++].y=j;                }            }        }        for(int i=0; i<t1; i++)        {            int l1=(a[i].x-1)*m+a[i].y;//以点建图            for(int j=0; j<t2; j++)            {                int l2=abs(a[i].x-b[j].x)+abs(a[i].y-b[j].y);                int l3=(b[j].x-1)*m+b[j].y;//以点建图                add(l1,l3,1,l2);            }        }        KM(s,t);    }    return 0;}

 

POJ2195:Going Home(费用流入门)