• poj-2195(最小费用流)


    题意:给你一个n*m的地图,H代表这个点有一个房子,m代表这个点是一个人,每次h走一步就花费一,问最小花费使得每个人能进入一个房间

    代码:建立一个源点和汇点,每个人和源点相连,每个房子和汇点相连,每个人和每个房子相连,花费为曼哈段距离

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int maxn=1005000;
    const int inf=0x3f3f3f3f;
    struct node
    {
        int x,y;
    }h[50050],man[50050];
    int cntm,cnth;
    struct Edge
    {
        int next;
        int to;
        int w;
        int cost;
    }edge[maxn];
    int head[50050],dist[50050],pre[50050],path[50050];
    int Start,End;
    char s[1050][1050];
    int cnt,x,y,w,n,m,tx,ty;
    void add(int u,int v,int w,int cost)
    {
      // cout<<u<<" "<<v<<" "<<w<<" "<<cost<<endl;
        edge[cnt].next=head[u];edge[cnt].to=v;
        edge[cnt].w=w;edge[cnt].cost=cost;head[u]=cnt++;
        //建回边
        edge[cnt].next=head[v];edge[cnt].to=u;
        edge[cnt].w=0;edge[cnt].cost=-cost;head[v]=cnt++;
    }
    bool spfa(int s,int t)
    {
        memset(pre,-1,sizeof(pre));
        memset(dist,inf,sizeof(dist));
        dist[s]=0;
        queue<int>q;
        q.push(s);
        while(!q.empty())//不能有环,建图的时候也要注意
        {
            int u=q.front();q.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(edge[i].w>0&&dist[u]+edge[i].cost<dist[v])//这条路径存在且能被优化
                {
                    dist[v]=dist[u]+edge[i].cost;
                    pre[v]=u;path[v]=i;q.push(v);
                }
            }
        }
        if(pre[t]==-1)
            return false;
        return true;
    }
    int mincost(int s,int t)
    {
        int cost=0;int flow=0;
        while(spfa(s,t))
        {
            int tempflow=inf;
            for(int u=t;u!=s;u=pre[u])//找最小的流量
            {
                if(edge[path[u]].w<tempflow)
                    tempflow=edge[path[u]].w;
            }
            flow+=tempflow;//每增广一次能得到的流量;
           //cost+=dist[t]*tempflow;//花费
            cost+=dist[t];
            for(int u=t;u!=s;u=pre[u])
            {
                edge[path[u]].w-=tempflow;
                edge[path[u]^1].w+=tempflow;
            }
        }
        return cost;
    }
    int main()
    {
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        while(cin>>n>>m)
        {
            if(n==0&&m==0)
                break;
            memset(head,-1,sizeof(head));
            cnt=cnth=cntm=0;
            Start=0;End=n*m+1;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                {
    
                    cin>>s[i][j];
                    if(s[i][j]=='m')
                    {
                        man[++cntm].x=i;man[cntm].y=j;
                    }
                    if(s[i][j]=='H')
                    {
                        h[++cnth].x=i;h[cnth].y=j;
                    }
                }
            for(int i=1;i<=cnth;i++)
            {
                y=End;x=(h[i].x-1)*m+h[i].y;
                add(x,y,1,0);
            }
            for(int i=1;i<=cntm;i++)
            {
                x=Start;y=(man[i].x-1)*m+man[i].y;
                add(x,y,1,0);
            }
            for(int i=1;i<=cntm;i++)
            {   x=man[i].x;y=man[i].y;
                for(int j=1;j<=cnth;j++)
                {
                    tx=h[j].x;ty=h[j].y;
                    w=abs(x-tx)+abs(y-ty);
                    add((x-1)*m+y,(tx-1)*m+ty,1,w);
                }
            }
            int ans=mincost(Start,End);
            cout<<ans<<endl;
        }
    }
    

      

  • 相关阅读:
    ASP.NET 2.0 正式版中无刷新页面的开发
    Flex在线录制视频并回放(源码)
    url重写
    在Web应用程序中执行计划任务
    添加类别和修改类别(无限级别分类)
    用C#制作新闻阅读器
    字符串处理
    编程珠玑随笔
    实现元素的全排列
    提高代码质量的三要素
  • 原文地址:https://www.cnblogs.com/huangdao/p/9991192.html
Copyright © 2020-2023  润新知