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 ;
    }
  • 相关阅读:
    SharePoint 2013 商务智能报表发布
    sharepoint designer web 服务器似乎没有安装microsoft sharepoint foundation
    SharePoint 2013 Designer系列之数据视图
    SharePoint 2013 Designer系列之数据视图筛选
    SharePoint 2013 Designer系列之自定义列表表单
    SharePoint 2013 入门教程之创建及修改母版页
    SharePoint 2013 入门教程之创建页面布局及页面
    SharePoint 2010 级联下拉列表 (Cascading DropDownList)
    使用SharePoint Designer定制开发专家库系统实例!
    PL/SQL Developer 建立远程连接数据库的配置 和安装包+汉化包+注册机
  • 原文地址:https://www.cnblogs.com/misty1/p/2607975.html
Copyright © 2011-2022 走看看