zoukankan      html  css  js  c++  java
  • POJ 2195 Going Home(最小费用最大流)

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

    题意 :  N*M的点阵中,有N个人,N个房子。让x个人走到这x个房子中,只能上下左右走,每个人每走一步就花1美元,问当所有的人都归位了之后,需要花多少美元。

    思路 :最小费用最大流。把人作为一个顶点集合U,房子作为另一个顶点集合V,把U中所有点到V中所有点连线,费用cost[u][v]为abs(△x)+abs(△y),反向弧费用cost[v][u]= -cost[u][v],容量cap[u][v]=1,构成一个多源多汇的二分图。 由于每一个多源多汇的网络流都必有一个与之对应的单源单汇的网络流,为了便于解题,由此构造一个超级源s和超级汇t,超级源s与U中所有点相连,费用cost[s][u]=0(这是显然的),容量cap[s][u]=1;V中所有点与超级汇t相连,费用cost[v][t]=0(这是显然的),容量cap[t][v]=1。至于其他不连通的点,费用与容量均为0。容量为0的边,可以理解为饱和边,不再连通。而上述的所有边之所以容量初始化为1,是因为每间房子只允许入住1个人。而与超级源(汇)相连的边的费用之所以为0,是为了现在所构造的单源单汇网络流最终所求的最小费用等于原来的多源多汇网络流的最小费用。

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <queue>
    #include <math.h>
    
    using namespace std;
    
    const int maxn = 210 ;
    struct node
    {
        int u ;
        int v ;
    }p[210],h[210] ;
    
    int pre[maxn],dist[maxn],n,m,pn,hn,s,t,cnt;
    int cap[maxn][maxn],flow[maxn][maxn],cost[maxn][maxn] ;
    bool flag[maxn] ;
    char ch[maxn][maxn] ;
    
    const int INF = 1000000000;
    
    void Init()
    {
        pn = hn = 0 ;
        cnt = s = 0 ;
        memset(cap,0,sizeof(cap)) ;
        memset(flow,0,sizeof(flow)) ;
        memset(cost,0,sizeof(cost)) ;
    }
    void spfa()
    {
        queue<int>Q ;
        for(int i = 0 ; i < maxn ; i++)
            dist[i] = INF ;
        memset(pre,-1,sizeof(pre)) ;
        memset(flag,false,sizeof(flag)) ;
        Q.push(s) ;
        flag[s] = true ;
        dist[s] = 0 ;
        while(!Q.empty())
        {
            int u = Q.front() ;
            Q.pop() ;
            flag[u] = false ;
            for(int v = 0 ; v <= t ; v++)
            {
                if(cap[u][v] && dist[v] > dist[u] + cost[u][v])
                {
                    dist[v] = dist[u] + cost[u][v] ;
                    pre[v] = u ;
                    if(!flag[v])
                    {
                        Q.push(v) ;
                        flag[v] = true ;
                    }
                }
            }
        }
    }
    
    void mcmf()
    {
        for( ; ; )
        {
            spfa() ;
            if(pre[t] == -1) break ;//没有父节点了,
            int x = t ,minn = INF ;
            while(pre[x] != -1)
            {
                minn = min(minn,cap[pre[x]][x]) ;
                x = pre[x] ;
            }
            x = t ;
            while(pre[x] != -1)
            {
                cap[pre[x]][x] -= minn ;
                cap[x][pre[x]] += minn ;
                cnt += minn*cost[pre[x]][x];
                x = pre[x];
            }
        }
    
    }
    
    int main()
    {
        while(scanf("%d %d",&n,&m) != EOF)
        {
            if(n == 0 && m == 0) break ;
            Init() ;
            for(int i = 0 ; i < n ; i++)
            {
                scanf("%s",ch[i]) ;
                for(int j = 0 ; j < m ; j++)
                {
                    if(ch[i][j] == 'H')
                    {
                        h[++hn].u = i ;
                        h[hn].v = j ;
                    }
                    else if(ch[i][j] == 'm')
                    {
                        p[++pn].u = i ;
                        p[pn].v = j ;
                    }
                }
            }
            t = pn+hn+1 ;
            for(int i = 1 ; i <= pn ; i++)
            cap[s][i] = 1 ;
            for(int i = 1 ; i <= hn ; i++)
            cap[i+pn][t] = 1 ;
            for(int i = 1 ; i <= pn ; i++)
            {
                for(int j = 1 ; j <= hn ; j++)
                {
                    cap[i][j+pn] = 1 ;
                    cost[i][j+pn] = fabs(p[i].u-h[j].u) + fabs(p[i].v-h[j].v) ;
                    cost[j+pn][i] = -cost[i][j+pn] ;
                }
            }
            mcmf() ;
            printf("%d
    ",cnt) ;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    垃圾回收算法(1)标记-清除
    golang的interface剖析
    库文件的使用
    linux loadavg详解(top cpu load)
    撰写的《大数据处理框架Apache Spark设计与实现》出版了
    VUE文件上传删除、图片上传删除、视频上传删除
    三元运算符
    VScode格式化后单引号变双引号解决办法
    VUE实现分页
    绝望!新手小白在VUE组件之间进行传值上浪费了很多时间~
  • 原文地址:https://www.cnblogs.com/luyingfeng/p/3544459.html
Copyright © 2011-2022 走看看