poj 2526 Minimum Cost【最小费用最大流】

题目链接:http://poj.org/problem?id=2516

题意:

n个店主 m个供应商 k种货物 给你店主对k种货物的需求及供货商k种货物的囤货量及K种运输费用。

解法:k次费用流,分别求每种货物的费用。源点到供应点建边,店主到汇点建边,费用均为0,容量为1。然后供应点到店主建边,费用为矩阵,容量无穷大即可。

代码:

/*
POJ 2195 Going Home
邻接矩阵形式最小费用最大流
*/

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;

//************************************************************
//最小费用最大流算法
//SPFA求最短路
//邻接矩阵形式
//初始化:cap:容量,没有边为0
//cost:耗费,对称形式,没有边的也为0
//c是最小费用
//f是最大流
//*******************************************************
const int MAXN = 500;
const int INF = 0x3fffffff;
int cap[MAXN][MAXN];//容量,没有边为0
int flow[MAXN][MAXN];
//耗费矩阵是对称的,有i到j的费用,则j到i的费用为其相反数
int cost[MAXN][MAXN];//花费

int n;//顶点数目0~n-1
int f;//最大流
int c;//最小费用
int start, End;//源点和汇点

bool vis[MAXN];//在队列标志
int que[MAXN];
int pre[MAXN];
int dist[MAXN];//s-t路径最小耗费
bool SPFA()
{
    int front = 0, rear = 0;
    for (int u = 0; u <= n; u++)
    {
        if (u == start)
        {
            que[rear++] = u;
            dist[u] = 0;
            vis[u] = true;
        }
        else
        {
            dist[u] = INF;
            vis[u] = false;
        }
    }
    while (front != rear)
    {
        int u = que[front++];
        vis[u] = false;
        if (front >= MAXN)front = 0;
        for (int v = 0; v <= n; v++)
        {
            if (cap[u][v]>flow[u][v] && dist[v]>dist[u] + cost[u][v])
            {
                dist[v] = dist[u] + cost[u][v];
                pre[v] = u;
                if (!vis[v])
                {
                    vis[v] = true;
                    que[rear++] = v;
                    if (rear >= MAXN)rear = 0;
                }
            }
        }
    }
    if (dist[End] >= INF)return false;
    return true;
}

void minCostMaxflow()
{
    memset(flow, 0, sizeof(flow));
    c = f = 0;
    while (SPFA())
    {
        int Min = INF;
        for (int u = End; u != start; u = pre[u])
            Min = min(Min, cap[pre[u]][u] - flow[pre[u]][u]);
        for (int u = End; u != start; u = pre[u])
        {
            flow[pre[u]][u] += Min;
            flow[u][pre[u]] -= Min;
        }
        c += dist[End] * Min;
        f += Min;
    }
}
//************************************************************

int tmp;
int a[10000][55];
int b[10000][55];

int main()
{
    int N, M, K;
    while (~scanf("%d%d%d", &N, &M, &K))
    {
        if (N == 0 && M == 0 && K == 0) break;
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));

        start = 0;
        n = N + M+ 2;
        End = M + N + 1;

        int need = 0;

        for (int i = 1; i <= N; i++)
        {
            for (int k = 1; k <= K;k++)
            {
                scanf("%d",&a[i][k]);
                need += a[i][k];
            }
        }

        for (int i = 1; i <= M; i++)
        {
            for (int k = 1; k <= K; k++)
            {
                scanf("%d", &b[i][k]);
            }
        }

        int ans = 0;
        int res = 0;

        for (int kk = 1; kk <= K; kk++)
        {
            memset(cap, 0, sizeof(cap));
            memset(cost, 0, sizeof(cost));

            for (int i = 1; i <= M; i++) //源点向供应点建边
                cap[start][i] = b[i][kk];
            for(int i = 1; i <= N; i++) //店主向汇点建边
                cap[M + i][End] = a[i][kk];

            for (int i = 1; i <= N; i++)
                for (int j = 1; j <= M; j++)
                {
                    scanf("%d", &tmp);
                    cost[j][i + M] = tmp;
                    cost[i + M][j] = -tmp;
                    cap[j][i + M] = 1000000;
                }
            minCostMaxflow();
            ans += c;
            res += f;
        }

        if (res == need)
            printf("%d\n", ans);
        else
            printf("-1\n");
    }
    return 0;
}

版权声明:转载请注明出处。

时间: 2024-10-03 15:01:50

poj 2526 Minimum Cost【最小费用最大流】的相关文章

POJ 2516 Minimum Cost(最小费用最大流,坑题)

题目链接:http://poj.org/problem?id=2516 题意:有N个店,M个供货商,K种商品.已知供货商的仓库里每种商品的数量以及每种商品运送到每个店的费用,每个店铺对各种商品的需求数量,求最少话费. Input  第一行:N,M,K. 然后1 - N行,每行 K列 ,第I行第J个数代表 第I个店铺 需要第J种物品多少件. 然后 N+1 - M行  ,每行 K列 , 第I行第J个数代表 第I个供货商 有第J种物品多少件. 然后是K个矩阵  ,每个N行M列,第ji个矩阵的第i行第j

POJ 2516 Minimum Cost (最小费用最大流)

Minimum Cost Time Limit: 4000MS   Memory Limit: 65536K       Description Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (marked from 1 to N) which stocks goods from him.Dearboy

Poj 2516 Minimum Cost (最小花费最大流)

题目链接: Poj  2516  Minimum Cost 题目描述: 有n个商店,m个仓储,每个商店和仓库都有k种货物.嘛!现在n个商店要开始向m个仓库发出订单了,订单信息为当前商店对每种货物的需求量.不同的商店从不同的仓库购买不同货物花费不同,问是不是能满足所有商店的要求,如果能商店花费总和最小为多少? 解题思路: 简单的费用流,要跑K次最小花费最大流,每次只对一种货物建图跑费用流.每次建图以0为源点, [1,m]为仓库, [m+1, n+m]为商店, n+m+1为汇点.0与[1,m]连边,

POJ 2195 Going Home (最小费用最大流)

题目链接:http://poj.org/problem?id=2195 题意:n*m的矩阵,地图上有若干个人(m)和房子(H),且人与房子的数量一致.man每移动一格费用为1,一个房子只能住一个人.现在要求所有的人出发,都入住房子,求最少话费. 思路:建立一个超级源点和汇点,源点与人相连费用为0,容量为1,人与房子相连,费用为人与房子的距离,容量为1,房子与汇点相连,费用为0,容量为1 #include <iostream> #include <cstdlib> #include

POJ 2195 地图的最小费用最大流

思路:这题刚开始看就知道是最小费用最大流了,因为求出最优嘛,而且要m,H要一一对应,所以不是二分图匹配就是最小费用最大流. 不过,刚开始还在想每个m与H之间的最小花费如何求,难道要用dfs搜索吗?这样想之后看了下题目给的时间是1000ms,然后就把dfs搜索m与H之间的最短距离排除了.然后想了想,其实尼玛太简单了,因为题目说了只能垂直与竖直的走,所以最短距离不就是两个横坐标相减与两个纵坐标相减之和嘛! 然后每对m与H之间都连边,流量为1(因为每对匹配不能重复),费用为它们之间的距离即花费:然后建

POJ 2195 - Going Home - [最小费用最大流][MCMF模板]

题目链接:http://poj.org/problem?id=2195 Time Limit: 1000MS Memory Limit: 65536K Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent

POJ 3680: Intervals【最小费用最大流】

题目大意:你有N个开区间,每个区间有个重量wi,你要选择一些区间,使得满足:每个点被不超过K个区间覆盖的前提下,重量最大 思路:感觉是很好想的费用流,把每个区间首尾相连,费用为该区间的重量的相反数(由于要最大,所以是求最大费用最大流),容量为1,至于不超过K的限制,只要从源点到第一个点的流量为K就行,剩下每个相邻的点相连,费用为0,流量只要大于的等于K就可以(我取的正无穷) //poj3680 #include <stdio.h> #include <iostream> #incl

POJ 2516 Minimum Cost 【费用流】

建模比较难想.. #include<iostream> #include<deque> #include<vector> #include<cstring> #include<cmath> #define INF 2e9 using namespace std; int T,ans; struct edge{ int v,cap,reverse,cost; }; vector<int> edges[1005];//邻接表 vector

POJ 2135 Farm Tour [最小费用最大流]

题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很难,因为要保证每条边只能走一次,那么我们把边拆为两个点,一个起点和终点,容量是1,权重是这条路的长度.然后两个端点分别向起点连接容量是1权重是0的边,终点分别向两个端点连容量是1权重是0的边,从源点到1连容量为2权重为0的边,从n到汇点连容量为2权重为0的边. #include<stdio.h>