PKU 2195 Going Home

来源:互联网 发布:java如何获取微信code 编辑:程序博客网 时间:2024/05/19 14:55

题目链接:

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

题解:

最小费用流

代码:

#include <cmath>#include <queue>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define inf 0x3f3f3f3f#define met(a,b) memset(a,b,sizeof(a))const int maxn = 200+10;struct node{    int to,next;    int flow,cost;}edge[maxn*maxn];int head[maxn],pre[maxn],path[maxn];int dis[maxn];int top;int s,t;vector<pair<int,int> >hh,mm;char mp[maxn][maxn];void init(){    met(head,-1);    top=0;}inline void Add(int u,int v,int w,int cost){    edge[top].to=v;    edge[top].flow=w;    edge[top].cost=cost;    edge[top].next=head[u];    head[u]=top++;}inline void Add_Edge(int u,int v,int w,int cost){    Add(u,v,w,cost);    Add(v,u,0,-cost);}int spfa(){    queue<int>q;    met(dis,inf);    met(pre,-1);    dis[s]=0;    q.push(s);    while(!q.empty())    {        int x=q.front();        q.pop();        for(int i=head[x];i!=-1;i=edge[i].next)        {            int y=edge[i].to;            if(edge[i].flow&&dis[y]>dis[x]+edge[i].cost)            {                dis[y]=dis[x]+edge[i].cost;                pre[y]=x;                path[y]=i;                q.push(y);            }        }    }    return pre[t]!=-1;}int MIN_FLOW(){    int cost=0;    int max_flow=0;    while(spfa())    {        int flow=inf;        for(int i=t;i!=s;i=pre[i])            flow=min(flow,edge[path[i]].flow);        for(int i=t;i!=s;i=pre[i])        {            int j=path[i];            edge[j].flow-=flow;            edge[j^1].flow+=flow;        }        max_flow+=flow;        cost+=flow*dis[t];    }    return cost;}inline int distance(int x1,int y1,int x2,int y2){    return abs(x1-x2)+abs(y1-y2);}int main(){    int n,m;    while(scanf("%d%d",&n,&m)&&n+m)    {        hh.clear(),mm.clear();        for(int i=1;i<=n;i++)        {            getchar();            for(int j=1;j<=m;j++)            {                scanf("%c",&mp[i][j]);                if(mp[i][j]=='m')                    mm.push_back(make_pair(i,j));                if(mp[i][j]=='H')                    hh.push_back(make_pair(i,j));            }        }        int h_len=(int)hh.size();        int m_len=(int)mm.size();        s=0,t=h_len+m_len+1;        init();        for(int i=1;i<=h_len;i++)            Add_Edge(s,i,1,0);        for(int i=0;i<h_len;i++)            for(int j=0;j<m_len;j++)            {                int cost=distance(hh[i].first,hh[i].second,mm[j].first,mm[j].second);                Add_Edge(i+1,j+h_len+1,1,cost);            }        for(int i=1;i<=m_len;i++)            Add_Edge(i+h_len,t,1,0);        printf("%d\n",MIN_FLOW());    }}
原创粉丝点击