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

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

    题意:N位店主,M个供应商品的地方,每个地方能供应K种商品,不同地方的不同的商品供应给不同的店主有不同的花费,如果这些店主能被供应,输出最小的花费,否则输出-1.

    思路:N位店主: 用编号为0~n-1的点表示

            M个供应商品的地方:用编号为 m~m+n-1的点表示

            m+n 代表超级源点,m+n+1 代表终极汇点

             用这些点建图,求最小费用最大流

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <queue>
      4 #include <algorithm>
      5 using namespace std;
      6 const int maxn=120;
      7 const int maxm=5000;
      8 const int INF=1<<28;
      9 struct node
     10 {
     11     int u,v,cap,cost;
     12     int next;
     13 } edge[maxm+maxm];
     14 int cnt,maxflow;
     15 bool vis[maxn];
     16 int head[maxn],dis[maxn],pre[maxn];
     17 int shop[maxn][maxn],sup[maxn][maxn],sum[maxn];
     18 void init()
     19 {
     20     cnt = 0;
     21     memset(head,-1,sizeof(head));
     22 }
     23 void add(int u,int v,int cap,int cost)//加双向边
     24 {
     25     edge[cnt].u = u;
     26     edge[cnt].v = v;
     27     edge[cnt].cap = cap;
     28     edge[cnt].cost = cost;
     29     edge[cnt].next = head[u];
     30     head[u] = cnt++;
     31     edge[cnt].u = v;
     32     edge[cnt].v = u;
     33     edge[cnt].cap = 0;
     34     edge[cnt].cost = -cost;
     35     edge[cnt].next = head[v];
     36     head[v] = cnt++;
     37 }
     38 int spfa(int s,int t,int n)//求增广路
     39 {
     40     memset(vis,false,sizeof(vis));
     41     memset(pre,-1,sizeof(pre));
     42     for (int i = 0; i < n; i++)
     43         dis[i] = INF;
     44     queue<int>q;
     45     q.push(s);
     46     vis[s] = true;
     47     dis[s] = 0;
     48     while(!q.empty())
     49     {
     50         int u = q.front();
     51         q.pop();
     52         vis[u] = false;
     53         for (int j = head[u]; j!=-1; j=edge[j].next)
     54         {
     55             int v = edge[j].v;
     56             int cost = edge[j].cost;
     57             if (edge[j].cap && dis[v] > dis[u]+cost)
     58             {
     59                 dis[v] = dis[u]+cost;
     60                 pre[v]=j;//v的前驱的下标
     61                 if (!vis[v])
     62                 {
     63                     q.push(v);
     64                     vis[v] = 1;
     65                 }
     66             }
     67         }
     68     }
     69     if (dis[t]==INF) return 0;
     70     return 1;//存在增广路
     71 }
     72 int min_cost_max_flow(int s,int t,int n)
     73 {
     74     int flow = 0,mincost=0,minflow;
     75     while(spfa(s,t,n))
     76     {
     77         minflow = INF+1;
     78         for (int i=pre[t]; i!=-1; i=pre[edge[i].u])
     79         {
     80             if (edge[i].cap < minflow)
     81                 minflow = edge[i].cap;
     82         }
     83         flow+=minflow;
     84         for (int i=pre[t]; i!=-1; i=pre[edge[i].u])//修改增广路
     85         {
     86             edge[i].cap-=minflow;
     87             edge[i^1].cap+=minflow;
     88         }
     89         mincost+=dis[t]*minflow;//最小花费
     90     }
     91     maxflow = flow;//最大流
     92     return mincost;
     93 }
     94 
     95 int main()
     96 {
     97     int n,m,k;
     98     while(~scanf("%d %d %d",&n,&m,&k))
     99     {
    100         if(n==0&&m==0&&k==0)
    101             break;
    102         memset(sum,0,sizeof(sum));
    103         for (int i = 0; i < n; i++)
    104         {
    105             for (int j = 0; j < k; j++)
    106             {
    107                 scanf("%d",&shop[i][j]);
    108                 sum[j]+=shop[i][j];
    109             }
    110         }
    111         for (int i = 0; i < m; i++)
    112         {
    113             for (int j = 0; j < k; j++)
    114             {
    115                 scanf("%d",&sup[i][j]);
    116             }
    117         }
    118         int flag = 1;
    119         int total = 0;
    120         for (int tt = 0; tt < k; tt++)
    121         {
    122             init();
    123             int price;
    124             for (int i = 0; i < n; i++)
    125             {
    126                 for (int j = 0; j < m; j++)
    127                 {
    128 
    129                     scanf("%d",&price);
    130                     add(j,m+i,INF,price);
    131                 }
    132             }
    133             if (flag==1)
    134             {
    135                 for (int i = 0; i < m; i++)
    136                 {
    137                     add(n+m,i,sup[i][tt],0);//增加超级源点
    138                 }
    139                 for (int j = 0; j < n; j++)
    140                 {
    141                     add(m+j,n+m+1,shop[j][tt],0);//增加终极汇点
    142                 }
    143                 int ans = min_cost_max_flow(m+n,m+n+1,m+n+2);//运送第tt种商品的最少花费
    144                 if (maxflow!=sum[tt])
    145                 {
    146                     flag = 0;
    147                 }
    148                 total+=ans;
    149             }
    150         }
    151         if (flag==1)
    152             printf("%d
    ",total);
    153         else
    154             printf("-1
    ");
    155     }
    156     return 0;
    157 }
    View Code

           

  • 相关阅读:
    矩阵论基础 3.1初等变换
    最优化理论与方法 9 二次规划
    最优化理论与方法 10 罚函数法
    矩阵论基础 2.5 用Matlab实现矩阵的基本运算
    最优化理论与方法 目录
    UG OPEN API编程基础 12UIStyler对话框
    第十四章 达朗伯原理 1
    矩阵论基础 2.3 方阵的几种运算
    矩阵论基础 3.5 用Matlab求解线性方程组
    测试一下博客的html代码机制
  • 原文地址:https://www.cnblogs.com/lahblogs/p/3481837.html
Copyright © 2011-2022 走看看