zoukankan      html  css  js  c++  java
  • poj 2516 Minimum Cost(最小费用最大流)

    题意:给出N的商店,M个仓库,K种物品,从这M个仓库给这N个商店供货,每条船有一定的载重量,商店和仓库间每一单元距离花费一定钱,求载货量最大而花费最小的情况。

    思路:典型的最小费用最大流,虽然是第一次做这样的题,但在昨天好好又把求最大流的方法看了一遍,所以感觉做这题不是很难,但是题目中的输入很让人纠结,建图建了很久。

    首先判断是否需求大于供应,如果是就直接输出-1,如果不是,直接用spfa求最小费用,将每种货物的最小花费加起来就是了。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #define N 105
    #define M 55
    #define INF 100000000
    using namespace std ;
    
    int cap[N][N] , cost[N][N] ;
    int n , m , k , s , e , sum ;
    int dis[N] , pre[N] , vist[N] ;
    int q[N] , top ;
    //通过一次BFS遍历找出费用最小一条路。
    int spfa ( )
    {
        int i , u , v ;
    
        for ( i = s ; i <= e ; i++ )
        {
            dis[i] = INF ;
            vist[i] = 0 ;
        }
        top = 0 ;
        q[top++] = s ;
        vist[s] = 1 ;
        dis[s] = 0 ;
        pre[s] = 0 ;
        while ( top )
        {
            u = q[--top] ;
            vist[u] = 0 ;
            for ( v = s ; v <= e ; v++ )
            {
                if ( cap[u][v] > 0 && dis[v] > dis[u] + cost[u][v] )
                {
                    dis[v] = dis[u] + cost[u][v] ;
                    pre[v] = u ;
                    if ( !vist[v] )
                    {
                        vist[v] = 1 ;
                        q[top++] = v ;
                    }
                }
            }
        }
        if ( dis[e] == INF ) return 0 ;
        return 1;
    }
    
    void cal ()
    {
        int u ;
        int minn = INF ;
        //找出条路中最小的容量
        for ( u = e ; u != s ; u = pre[u] )
        {
            minn = minn < cap[pre[u]][u] ? minn : cap[pre[u]][u] ;
        }
        for ( u = e ; u != s; u = pre[u] )
        {
            cap[pre[u]][u] -= minn ;
            cap[u][pre[u]] += minn ;
            sum += cost[pre[u]][u] * minn ;
        }
    }
    
    int main()
    {
        int need[N][N] , needx[N] , have[N][N] , havex[N] ;
        int i , j , c ;
    
        while ( scanf ( "%d%d%d" , &n , &m , &k ) != EOF )
        {
            if ( n == 0 && m == 0 && k == 0 )
            break;
            //n个商店要求的k中货物的总量
            memset( needx , 0 , sizeof( needx ));
            for ( i = 1 ; i <= n ; i++ )
            {
                for ( j = 1 ; j <= k ; j++ )
                {
                    scanf ( "%d" , &need[i][j] );
                    needx[j] += need[i][j] ;
                }
            }
            //m个仓库所存储的货物总量
            memset( havex , 0 , sizeof( havex ));
            for ( i = 1 ; i <= m ; i++ )
            {
                for ( j = 1 ; j <= k ; j++ )
                {
                    scanf ( "%d" , &have[i][j] );
                    havex[j] += have[i][j] ;
                }
            }
            //判断是否有货物的存储量小于需求量
            int flag = 0 ;
            for ( i = 1 ; i <= k ; i++ )
            if ( needx[i] > havex[i] )
            {
                flag = 1 ;break;
            }
            s = 0 ;//超级源点
            e = n + m + 1;//超级汇点
            sum = 0;
            for ( c = 1 ; c <= k ; c++ )
            {
                memset( cap , 0 , sizeof ( cap ));
                memset( cost , 0 , sizeof ( cost ));
                //输入仓库j到i的费用
                for ( i = 1 ; i <= n ; i++ )
                {
                    for ( j = 1 ; j <= m ; j++ )
                    {
                        scanf( "%d" , &cost[j][m+i] );
                        cost[m+i][j] = -cost[j][m+i] ;
                        cap[j][m+i] = INF ;
                    }
                }
                if ( flag )
                continue ;
                //将所有仓库与超级源点相连。
                for ( i = 1 ; i <= m ; i++ )
                {
                    cost[s][i] = cost[i][s] = 0 ;
                    cap[s][i] = have[i][c] ;
                }
                //所有商店与超级汇点相连
                for ( i = 1; i <= n ; i++ )
                {
                    cost[m+i][e] = cost[e][m+i] = 0 ;
                    cap[m+i][e] = need[i][c] ;
                }
                //sum = 0 ;
                while ( spfa ()) cal();
            }
            if ( flag )
            printf ( "-1\n" );
            else
            printf ( "%d\n" , sum );
        }
        return 0 ;
    }
  • 相关阅读:
    Ansible安装配置
    软件测试流程与测试文档
    软件测试与软件质量
    软件测试模型
    软件测试基础知识
    阮一峰ES6
    微信小程序引用外部js,引用外部样式,引用公共页面模板
    css中class后面跟两个类,这两个类用空格隔开
    动态设置WX滚动条的高度(非常重要)
    Vue入口页
  • 原文地址:https://www.cnblogs.com/misty1/p/2607975.html
Copyright © 2011-2022 走看看