zoukankan      html  css  js  c++  java
  • 网络流之最大流

    什么是网络流: 

      网络流就是给出一个图,然后每条边上有一个最大的流量(容量),只有出流没有入流的点叫做源点,只有入流没有出流的点叫做汇点

    残余网络:

      不断地给每条边分配流量,然后用其剩余的容量减去这些流量,得到残量,残量构成残余网络

    增广路:

      在残余网络中,还可以继续分配流量的路径(该路径上每条流的残量都不为0)叫做增广路

     依据以上定义,可以得出三条性质:

      (1) 每条流的流量一定小于容量

      (2)每个点的入流与出流相等

      (3)从u到v的流量=从v到u的流量的相反数

    网络流最大

      最大流算法就是指求一种流量方案,使得从源点到汇点的流量最大

    求解:

      每次去dfs找增广路,然后将增广路上每条流都减去最小的那条流的残量,也就是将该增广路上的一条流的残量变为0,直到找不到增广路为止。

      但是发现这样是有问题的,

      比如上面这种情况,本来增广路选择的是从u->v,但是可以找到两个点q,p达成以上情况,使得流量变大。这时候就要用到反向边,在加边的时候同时加上一条反边,如图3,这样在更新p和q的时候就会走这条反边,然后利用性质3,每将正边减去一个流之后,都将这条反边加上这条流。

     Dinic算法:

      如果用上面的方法去跑下面的情况

      

       最优的跑法应该是s->v->t但是,程序可能会s->v->u->t,然后就会出现下面的情况

      

      如果有很不慎,程序又跑了s->u->v->t然后就会

      这样每次更新1,就要跑999*2次深搜,如果比999更大,就很容易tle,所以就有了Dinic算法

      Dinic算法就是在bfs的同时,记录下每个点的深度,比如上面第一次bfs之后各个点的深度:s(0),v(1),u(1),t(2) 

      然后在dfs的时候,就只去更新深度比自己大1的。这时候上面的例子中,一开始就不会出现s->v->u->t的情况,因为v和u的深度相同。

    一道板子题:

      洛谷3376

    代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<queue>
     4 #include<cstring>
     5 #define change(i) i%2?(i+1):(i-1)
     6 using namespace std;
     7 const int INF=0x7fffffff;
     8 const int N=10010,M=100010;
     9 int ejs,n,m,s,t;
    10 int head[N],dep[N];
    11 queue<int>q;
    12 struct node
    13 {
    14     int v,w,nxt;
    15 }edg[M*2];
    16 void add(int u,int v,int w)
    17 {
    18     edg[++ejs].v=v;
    19     edg[ejs].w=w;
    20     edg[ejs].nxt=head[u];
    21     head[u]=ejs;
    22 }
    23 inline bool bfs()
    24 {
    25     while(!q.empty())
    26     q.pop();
    27     memset(dep,0,sizeof(dep));
    28     dep[s]=1;
    29     q.push(s); 
    30     while(!q.empty())
    31     {
    32         int u=q.front();
    33         q.pop();
    34         for(int i=head[u];i;i=edg[i].nxt)
    35         {
    36             int v=edg[i].v;
    37             if(!dep[v]&&edg[i].w)
    38             {
    39                 dep[v]=dep[u]+1;
    40                 q.push(v); 
    41             }
    42         }
    43     }
    44     if(dep[t])
    45     return 1;
    46     return 0;
    47 }
    48 int dfs(int u,int dist)
    49 {
    50     if(u==t)
    51         return dist;
    52     for(int i=head[u];i;i=edg[i].nxt)
    53     {
    54         int v=edg[i].v;
    55         if((dep[v]==dep[u]+1)&&edg[i].w)
    56         {
    57             int di=dfs(v,min(dist,edg[i].w));
    58             if(di>0)
    59             {
    60                 edg[i].w-=di;
    61                 edg[change(i)].w+=di;
    62                 return di;
    63             }
    64         }
    65     }
    66     return 0;
    67 }
    68 inline int dinic()
    69 {
    70     int ans=0;
    71     while(bfs())
    72     {
    73         int d=0;
    74         do
    75         {
    76             d=dfs(s,INF);
    77             ans+=d;
    78         }while(d);
    79     }
    80     return ans;
    81 }
    82 int main()
    83 {
    84     scanf("%d%d%d%d",&n,&m,&s,&t);
    85     for(int i=1,u,v,w;i<=m;++i)
    86     {
    87         scanf("%d%d%d",&u,&v,&w);
    88         add(u,v,w);
    89         add(v,u,0);
    90     }
    91     printf("%d",dinic());
    92     
    93     return 0;
    94 } 
    luogu3376

    PS :以上内容均参(chao)考(xi)一位大佬的博客

  • 相关阅读:
    【异常】No ManagedConnections available within configured blocking timeout
    【异常】Caused by: java.lang.ClassNotFoundException: org.springframework.dao.DataIntegrityViolationException
    【Redis】:Jedis 使用
    【异常】INFO: TopologyManager: EndpointListener changed ...
    【Java】JDK类 CountDownLatch
    【WEB】一个简单的WEB服务器
    【JAVA】Socket 编程
    【JBOSS】 JBOSS目录结构
    [SE0]简单的搜索引擎原理
    【ORACLE】 表空间信息
  • 原文地址:https://www.cnblogs.com/wxyww/p/9298188.html
Copyright © 2011-2022 走看看