zoukankan      html  css  js  c++  java
  • 最小费用最大流

    思想:
    采用贪心的思想。 通过SPFA,增广路的思想,每次找到一条从源点到达汇点的花费最小的路径

     1  if(e.flow>0&&dis[e.v]>dis[now]+e.cost)
     2             {
     3                 dis[e.v]=dis[now]+e.cost; //维护最小费用
     4                 addflow[e.v]=min(addflow[now],e.flow);//维护流量
     5                 pre[e.v]=i;//将点指向上一条边,方便回溯
     6  
     7                 if(!vis[e.v])
     8                 {
     9                     q.push(e.v);
    10                     vis[e.v]=1;
    11                 }
    12             }

    增加流量,直到无法找到一条从源点到达汇点的路径,算法结束。 每次找一条花费最小的路径,从源点跑到汇点,然后维护这条路上所加的流量最小值(addflow函数),然后总流量加上流量。最后再回溯,将正向边减去,反向边加上流量。找到一条路径。再while循环这个过程,直到找不到S到T的点;这样每次找的边都保证费用最小,每次增加流量,直到没有路径增加,得到最小费用最大流;

    回溯算法如下:

    1  while(now!=s)
    2     {
    3         edg[pre[now]].flow-=addflow[t];
    4         edg[pre[now]^1].flow+=addflow[t];
    5         now=edg[pre[now]].u;
    6     }
    View Code

    由于最大流量有限,每执行一次循环流量都会增加,因此该算法肯定会结束,且同时流量也必定会达到网络的最大流量;同时由于每次都是增加的最小的花费,即当前的最小花费是所有到达当前流量flow时的花费最小值,因此最后的总花费最小。

    板子如下:

    原题为:

    问题D:海上采矿站

    时间限制: 1秒   内存限制: 128 MB 

    题目描述

    海洋是资源的宝库,人类社会的发展越来越依赖于它。为了开发和利用海洋资源,有必要在海上建立采矿站。然而,由于海底矿物资源,海洋中的无线电信号通常很弱,以至于并非所有采矿站都能进行直接通信。然而,通信是必不可少的,每两个采矿站必须能够相互通信(直接或通过其他一个或多个采矿站)。为了满足将开采资源运到陆地投入使用的需要,沿海岸相应建设n个港口,每个港口可以直接与一个或多个采矿站通信。

    由于一些采矿站不能直接相互通信,为了船舶导航的安全,船只只允许在可以直接相互通信的采矿站之间航行。 

    采矿是艰巨的,人们做这项工作需要适当的休息(也就是说,让船只返回港口)。但真是巧合!这次,n艘采矿船只轮流在同一时间休息。它们分散在不同的站点,现在它们必须返回港口,此外,一个港口只能容纳一艘船。现在所有船只将开始返回,如何选择他们的航行路线,使他们的航行路线的总和最小。 

    请注意,一旦船舶进入港口,它就不会出来!
     


    输入

    有几个测试用例。每个测试用例以一行中的四个整数开始,n(1 = <n <= 100),m(n <= m <= 200),k和p。n表示n个船只和n个港口,m表示m个采矿站,k表示k个边缘,每个边缘对应于li在采矿站和另一个采矿站之间的nk,p表示p个边缘,每个边缘指示link在港口和采矿站之间。以下行是n个整数,每个整数表示一个船只所属的一个站点。然后是k行,每行包括3个整数a,b和c,表明在采矿站a和b之间存在直接通信并且它们之间的距离是c。最后,接着是另外的p行,每行包括3个整数d,e和f,表明端口d和采矿站e之间存在直接通信,它们之间的距离为f。此外,采矿站由1到m的数字和端口1到n表示。输入由文件结束终止。


    输出

    每个测试用例输出其航行路线的最小总和。


    样例输入

    3 5 5 6
    1 2 4
    1 3 3
    1 4 4
    1 5 5
    2 5 3
    2 4 3
    1 1 5
    1 5 3
    2 5 3
    2 4 6
    3 1 4
    3 2 2
    

    样例输出

    13
    

     

      1 #include<bits/stdc++.h>
      2 #define INF INT_MAX/2
      3 #define N 310
      4 using namespace std;
      5  
      6 typedef struct
      7 {
      8     int u,v,next;
      9     int flow,cost;
     10 }ss;
     11  
     12 ss edg[N*N*4];
     13 int head[N];
     14 int now_edge=0;
     15  
     16 void init()
     17 {
     18     memset(head,-1,sizeof(head));
     19     now_edge=0;
     20 }
     21  
     22 void inline addedge(int u,int v,int flow,int cost)
     23 {
     24     edg[now_edge]=(ss){u,v,head[u],flow,cost};
     25     head[u]=now_edge++;
     26     edg[now_edge]=(ss){v,u,head[v],0,-cost};
     27     head[v]=now_edge++;
     28 }
     29  
     30  
     31 int dis[N];
     32 int vis[N]={0};
     33 int addflow[N]={0};
     34 int pre[N]={0};
     35 queue<int>q;
     36  
     37 bool spfa(int s,int t,int &flow,int &cost)
     38 {
     39     for(int i=0;i<N;i++)
     40     {
     41         dis[i]=INF;
     42         vis[i]=0;
     43     }
     44  
     45     while(!q.empty())q.pop();
     46     dis[s]=0;
     47     vis[s]=1;
     48     q.push(s);
     49     addflow[s]=INF;
     50     while(!q.empty())
     51     {
     52         int now=q.front();
     53         q.pop();
     54         vis[now]=0;
     55  
     56         for(int i=head[now];i!=-1;i=edg[i].next)
     57         {
     58             ss e=edg[i];
     59  
     60             if(e.flow>0&&dis[e.v]>dis[now]+e.cost)
     61             {
     62                 dis[e.v]=dis[now]+e.cost;
     63                 addflow[e.v]=min(addflow[now],e.flow);
     64                 pre[e.v]=i;
     65  
     66                 if(!vis[e.v])
     67                 {
     68                     q.push(e.v);
     69                     vis[e.v]=1;
     70                 }
     71             }
     72         }
     73     }
     74  
     75     if(dis[t]==INF)return false;
     76  
     77     flow+=addflow[t];
     78     cost+=addflow[t]*dis[t];
     79  
     80     int now=t;
     81     while(now!=s)
     82     {
     83         edg[pre[now]].flow-=addflow[t];
     84         edg[pre[now]^1].flow+=addflow[t];
     85         now=edg[pre[now]].u;
     86     }
     87  
     88     return true;
     89 }
     90  
     91 void MCMF(int s,int t,int &flow,int &cost)
     92 {
     93     while(spfa(s,t,flow,cost));
     94 }
     95  
     96  
     97  
     98 int main()
     99 {
    100     int n,m,p,k;
    101     while(scanf("%d %d %d %d",&n,&m,&k,&p)==4)
    102     {
    103         init();
    104         int s=n+m+1;
    105         int t=s+1;
    106  
    107         for(int i=1;i<=n;i++)
    108         {
    109             int a;
    110             scanf("%d",&a);
    111             addedge(s,a+n,1,0);
    112         }
    113  
    114         while(k--)
    115         {
    116             int u,v,w;
    117             scanf("%d %d %d",&u,&v,&w);
    118             addedge(n+u,n+v,INF,w);
    119             addedge(n+v,n+u,INF,w);
    120         }
    121  
    122         while(p--)
    123         {
    124             int u,v,w;
    125             scanf("%d %d %d",&u,&v,&w);
    126             addedge(n+v,u,INF,w);
    127         }
    128  
    129         for(int i=1;i<=n;i++)addedge(i,t,1,0);
    130         int flow=0,cost=0;
    131         MCMF(s,t,flow,cost);
    132         printf("%d
    ",cost);
    133     }
    134  
    135     return 0;
    136 }
  • 相关阅读:
    像计算机科学家一样思考python-第3章 函数
    jenkins打包ios 报错rror: No signing certificate "iOS Distribution" found: No "iOS Distribution...
    为什么 自动化打包可以打出包,但是包的内容与代码内容不符?
    ios 无法安装xxx,请稍后再试
    error: exportArchive: You don’t have permission to save the file “HelloWorld.ipa” in the folder “HelloWorld”.
    tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
    xcode archive灰色,无法打包的解决办法
    Build Android-x86 ICS 4 Virtualbox from Google Virtualbox Target and Intel Kernel 编译体验
    Vim简明教程【CoolShell】(转)
    ubuntu10.04版本下android源码的编译
  • 原文地址:https://www.cnblogs.com/sylvia1111/p/11317481.html
Copyright © 2011-2022 走看看