• 最小费用最大流


    1、Educational Codeforces Round 29 F.Almost Permutation

    (见CF题记《Educational Codeforces Round 29》)

    2、uva 11613 Acme Corporation

      题意:有M月,X元素每个月单位保存费用为I,在每个月中,单位生产成本为ni,最大生产数目为mi,单位销售价格为pi,最大销售限制为si,当月生产的X元素最多保存Ei个月份(比如i=1,Ei=3,则可保存月份为1,2,3,4,当月卖出当然不用存储,保存费用为0)。求最大利润?

      思路:采用最小费用最小流,因为本题求最大利润,所有的消耗取正,所有的利润取负,如果当前利润为正,表示已经亏本,停止增广。建立源点,向每个月份建边,容量为mi,边权为ni;每个月向汇点建边,容量为si,边权为-pi;每个月份i向所能保存到的月份j建边,容量为INF,边权为I*(j-i).

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 using namespace std;
      6 
      7 const int maxn = 510;
      8 const int maxe = (maxn + maxn + maxn*maxn) * 2 + 10;
      9 const int INF = 0x3f3f3f3f;
     10 struct edge
     11 {
     12     int from, to, cap, flow, cost, next;
     13     edge(int ff=0,int tt=0,int cc=0,int ww=0,int ss=0,int nn=0):from(ff),to(tt),cap(cc),flow(ww),cost(ss),next(nn){ }
     14 }Edge[maxe];
     15 int Head[maxn], totedge;
     16 
     17 struct MCMF
     18 {
     19     int pre[maxn];//记录在增广路径上,到达i的边的编号
     20     int dist[maxn];
     21     bool vis[maxn];
     22     int N,st,ed;
     23 
     24     void Init()
     25     {
     26         memset(Head, -1, sizeof(Head));
     27         totedge = 0;
     28     }
     29 
     30     void Set(int nodes, int source, int dest)
     31     {
     32         N = nodes, st = source, ed = dest;
     33     }
     34 
     35     void addedge(int from, int to, int cap, int cost)
     36     {
     37         Edge[totedge] = edge(from, to, cap, 0, cost, Head[from]);
     38         Head[from] = totedge++;
     39         Edge[totedge] = edge(to, from, 0, 0, -cost, Head[to]);
     40         Head[to] = totedge++;
     41     }
     42 
     43     bool SPFA(int s, int t)//跑一遍SPFA 找s——t的最少花销路径 且该路径上每一条边不能满流 ,若存在 说明可以继续增广,反之不能  
     44     {
     45         queue<int>q;
     46         memset(dist, INF , sizeof(dist));
     47         memset(vis, 0, sizeof(vis));
     48         memset(pre, -1, sizeof(pre));
     49         
     50         dist[s] = 0;
     51         vis[s] = true;
     52         q.push(s);
     53         while (!q.empty())
     54         {
     55             int u = q.front();
     56             q.pop();
     57             vis[u] = false;
     58 
     59             for (int i = Head[u]; i != -1; i = Edge[i].next)
     60             {
     61                 if (dist[Edge[i].to] > dist[u] + Edge[i].cost&&Edge[i].cap > Edge[i].flow)
     62                 {
     63                     dist[Edge[i].to] = dist[u] + Edge[i].cost;
     64                     pre[Edge[i].to] = i;
     65                     if (!vis[Edge[i].to])
     66                     {
     67                         vis[Edge[i].to] = true;
     68                         q.push(Edge[i].to);
     69                     }
     70                 }
     71             }
     72         }
     73         return pre[t] != -1&&dist[t]<=0;
     74     }
     75 
     76     void cal_MCMF(long long&cost,long long&flow)
     77     {
     78         flow = 0, cost = 0;
     79         while (SPFA(st, ed))
     80         {
     81             //通过反向弧,在源点到汇点的最少花费路径 找最小增广流
     82             int Min = INF;
     83             for (int i = pre[ed]; i != -1; i = pre[Edge[i ^ 1].to])
     84             {
     85                 Min = min(Min, Edge[i].cap - Edge[i].flow);
     86             }
     87             //增广
     88             for (int i = pre[ed]; i != -1; i = pre[Edge[i ^ 1].to])
     89             {
     90                 Edge[i].flow += Min;
     91                 Edge[i ^ 1].flow -= Min;
     92                 cost +=1ll*Edge[i].cost*Min;
     93             }
     94             flow += Min;
     95         }
     96     }
     97 }mcmf;
     98 
     99 int M, I;//总月份,每保存一个月的花费
    100 struct node
    101 {
    102     int mi, ni, pi, si, Ei;//单位生产费用;最大生产量;单位销售价格;最大销售量限制;可保存月份
    103     node(int mm=0,int nn=0,int pp=0,int ss=0,int ee=0):mi(mm),ni(nn),pi(pp),si(ss),Ei(ee){ }
    104 }parameters[110];
    105 int main()
    106 {
    107     int t;
    108     scanf("%d", &t);
    109     int Case = 1;
    110     while (t--)
    111     {
    112         scanf("%d%d", &M, &I);
    113         for (int i = 1; i <= M; i++)
    114         {
    115             scanf("%d%d%d%d%d", &parameters[i].mi, &parameters[i].ni, &parameters[i].pi, &parameters[i].si, &parameters[i].Ei);
    116         }
    117         mcmf.Init();
    118         mcmf.Set(2 * M + 2, 0, 2 * M + 1);
    119         for (int i = 1; i <= M; i++)
    120         {
    121             mcmf.addedge(0, 2 * i - 1, parameters[i].ni, parameters[i].mi);//本题求最大利润,费用+
    122             mcmf.addedge(2 * i, 2 * M + 1, parameters[i].si,-parameters[i].pi);//本题求最大利润,卖出-
    123         }
    124         for (int i = 1; i <= M; i++)
    125         {
    126             for (int j = i; j <= min(i + parameters[i].Ei, M); j++)
    127             {
    128                 mcmf.addedge(2 * i - 1, 2 * j, INF, I*(j - i));//I*(j - i)表示每单位从i月保存至j月需要的费用
    129             }
    130         }
    131         long long flow, cost;
    132         mcmf.cal_MCMF(cost, flow);
    133         printf("Case %d: %lld
    ", Case++, -cost);
    134     }
    135     return 0;
    136 }
    View Code

     3、uva 10806 Dijkstra, Dijkstra

      题意:有n个结点,监狱在1,车站在n,一共有m条无向边,每条边有一个边权表示走这条的时间花费,每条边只能走一次。现在有两个人要从监狱逃出,求能否达到车站,且时间最短?

      思路:设一个源点,到监狱1建边,容量为2,花费为0;每条无向边拆成两条有向边,容量为1,边权为时间花费。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<queue>
      5 #include<cstring>
      6 using namespace std;
      7 const int maxn = 110;
      8 const int maxe = maxn*maxn*4+10;
      9 const int INF = 0x3f3f3f3f;
     10 struct edge
     11 {
     12     int from, to, cap, flow, cost, next;
     13     edge(int ff = 0, int tt = 0, int cc = 0, int ww = 0, int ss = 0, int nn = 0) :from(ff), to(tt), cap(cc), flow(ww), cost(ss), next(nn){ }
     14 }Edge[maxe];
     15 int Head[maxn], totedge;
     16 
     17 struct MCMF
     18 {
     19     int pre[maxn];
     20     int dist[maxn];
     21     bool vis[maxn];
     22     int N, st, ed;
     23 
     24     void Init()
     25     {
     26         memset(Head, -1, sizeof(Head));
     27         totedge = 0;
     28     }
     29 
     30     void set(int nodes, int source, int dest)
     31     {
     32         N = nodes, st = source, ed = dest;
     33     }
     34 
     35     void addedge(int from, int to, int cap, int cost)
     36     {
     37         Edge[totedge] = edge(from, to, cap, 0, cost, Head[from]);
     38         Head[from] = totedge++;
     39         Edge[totedge] = edge(to, from, 0, 0, -cost, Head[to]);
     40         Head[to] = totedge++;
     41     }
     42 
     43     bool SPFA()
     44     {
     45         queue<int>q;
     46         memset(dist, INF, sizeof(dist));
     47         memset(vis, 0, sizeof(vis));
     48         memset(pre, -1, sizeof(pre));
     49 
     50         dist[st] = 0;
     51         vis[st] = true;
     52         q.push(st);
     53         while (!q.empty())
     54         {
     55             int u = q.front();
     56             q.pop();
     57             vis[u] = false;
     58 
     59             for (int i = Head[u]; i != -1; i = Edge[i].next)
     60             {
     61                 if (dist[Edge[i].to] > dist[u] + Edge[i].cost&&Edge[i].cap > Edge[i].flow)
     62                 {
     63                     dist[Edge[i].to] = dist[u] + Edge[i].cost;
     64                     pre[Edge[i].to] = i;
     65                     if (!vis[Edge[i].to])
     66                     {
     67                         vis[Edge[i].to] = true;
     68                         q.push(Edge[i].to);
     69                     }
     70                 }
     71             }
     72         }
     73         return pre[ed] != -1;
     74     }
     75 
     76     void cal_MCMF(int &cost, int &flow)
     77     {
     78         flow = 0, cost = 0;
     79         while (SPFA())
     80         {
     81             int Min = INF;
     82             for (int i = pre[ed]; i != -1; i = pre[Edge[i ^ 1].to])
     83             {
     84                 Min = min(Min, Edge[i].cap - Edge[i].flow);
     85             }
     86             for (int i = pre[ed]; i != -1; i = pre[Edge[i ^ 1].to])
     87             {
     88                 Edge[i].flow += Min;
     89                 Edge[i ^ 1].flow -= Min;
     90                 cost += Edge[i].cost*Min;
     91             }
     92             flow += Min;
     93         }
     94     }
     95 }mcmf;
     96 
     97 int n, m;
     98 int main()
     99 {
    100     while (~scanf("%d", &n) && n)
    101     {
    102         scanf("%d", &m);
    103         mcmf.Init();
    104         mcmf.set(n + 1, 0, n);
    105         mcmf.addedge(0, 1, 2, 0);
    106         for (int i = 1; i <= m; i++)
    107         {
    108             int u, v, c;
    109             scanf("%d%d%d", &u, &v, &c);
    110             mcmf.addedge(u, v, 1, c);
    111             mcmf.addedge(v, u, 1, c);
    112         }
    113         int cost, flow;
    114         mcmf.cal_MCMF(cost, flow);
    115         if (flow == 2) printf("%d
    ", cost);
    116         else printf("Back to jail
    ");
    117     }
    118     return 0;
    119 }
    View Code
  • 相关阅读:
    协议分析 - DHCP协议解码详解
    在SqlServer2000的视图中小心使用*符号
    sql 将 varchar 值转换为数据类型为 int 的列时发生语法错误 的解决办法
    LECCO SQL Expert工具之优化sql语句
    css+js简单应用
    对任何一天是星期几算法的实现
    asp.net ajax 1.0 出现"sys"未定义解决方法
    js日历脚本
    在ASP.NET中重写URL
    在ASP.NET中重写URL (续篇)
  • 原文地址:https://www.cnblogs.com/ivan-count/p/7594644.html
Copyright © 2020-2023  润新知