POJ-2195 Going Home (Expense Flow)

Question: There are n houses and n people on a 100*100 map (n<=100). The distance between each person and the house is Cartesian coordinates and is not affected by obstacles. Ask everyone to return to a separate home Minimum cost required

Establish a super source point and a super sink point, each side has a flow of 1, so that everyone can match a house at the maximum flow, and then the required cost will be allocated between each person and each house , Just run the cost flow board.

The details that need to be paid attention to when setting up the board include the starting point and the end point being 0 and t1*2+1, and the cost is one cost per side instead of one cost per flow. You need to change the board.

#include <cmath> //定义数学函数
#include <cstdio> //定义输入/输出函数
#include <iostream>
#include <queue> //STL 队列容器
#define x first
#define y second
using namespace std;
typedef pair<int,int>pii;
const int maxn = 1e3 + 10;
const int maxm = 1e5 + 10;
const int inf = 0x3f3f3f3f;

struct Edg
{
    int to,flow,cost,nxt;//下个点、流量、费用、前项星
}edg[maxm];//从0开始存边
int edg_cnt,head[maxn];//从1开始存点
void addedg(int a,int b,int c,int d)
{
    edg[edg_cnt]={b,c,d,head[a]};
    head[a]=edg_cnt++;
    edg[edg_cnt]={a,0,-d,head[b]};
    head[b]=edg_cnt++;
}

int n,m,s,t;
int t1,t2;
int pre[maxn],dis[maxn];
bool vis[maxn];

bool spfa()
{
    for(int i=s;i<=t;i++)
    {
        dis[i]=inf;
        vis[i]=0;
        pre[i]=-1;
    }
    dis[s]=0;
    queue<int>q;
    q.push(s);vis[s]=1;
    while(!q.empty())
    {
        int u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];~i;i=edg[i].nxt)
        {
            int v=edg[i].to;
            if(edg[i].flow&&dis[v]>dis[u]+edg[i].cost)
            {
                dis[v]=dis[u]+edg[i].cost;
                pre[v]=i;
                if(!vis[v])
                {
                    q.push(v);vis[v]=1;
                }
            }
        }
    }
    return pre[t]!=-1;
}
 
void costflow()
{
    int cost=0;
    while(spfa())
    {
        int mi=inf;
        for(int i=pre[t];~i;i=pre[edg[i^1].to])
        {
            mi=min(mi,edg[i].flow);
            cost+=edg[i].cost;
        }
        for(int i=pre[t];~i;i=pre[edg[i^1].to])
        {
            edg[i].flow-=mi;
            edg[i^1].flow+=mi;
        }
    }
    printf("%d\n",cost);
}

string str[110];
pii hs[110],man[110];
int main()
{
    // freopen("in.txt","r",stdin);
    while(1)
    {
        scanf("%d%d",&n,&m);
        if(!n&&!m)break;
        t1=0,t2=0,edg_cnt=0;
        for(int i=0;i<n;i++)
        {
            cin>>str[i];
            for(int j=0;j<m;j++)
            {
                if(str[i][j]=='H')hs[++t1]={i,j};
                else if(str[i][j]=='m')man[++t2]={i,j};
            }
        }
        s=0,t=t1*2+1;
        for(int i=s;i<=t;i++)head[i]=-1;
        for(int i=1;i<=t1;i++)
        {
            addedg(0,i,1,0);
            addedg(i+t1,t,1,0);
        }
        for(int i=1;i<=t1;i++)
        {
            for(int j=1;j<=t1;j++)
            {
                addedg(i,j+t1,1,abs(hs[i].x-man[j].x)+abs(hs[i].y-man[j].y));
            }
        }
        costflow();
    }
    return 0;
}

 

Guess you like

Origin blog.csdn.net/qq_43700916/article/details/104226199