码迷,mamicode.com
首页 > 其他好文 > 详细

【您有新的未分配天赋点】网络流:从懵逼到完全懵逼

时间:2017-07-29 21:23:50      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:重要   通过   比较   最大流   最小   删除   eof   pre   nic   

今天呢@assassain julao讲了一个在OI中极其重要,极其有趣,把无数人坑退役的知识点:网络流。

网络流呢顾名思义,就是在一个图中边有流量的限制,并根据这些流量限制做一些跟这个有关的事(ti)情(mu)。什么,范围?按zzh神犇的话来说,就是考试中那些看上去像是dp却又推不出式子的问题的通用解法

按照问题的倾向,我们将问题分为三类:最大流、最小割、最小费用流。

大家看好我要开始口胡了

首先我们研究最大流,介绍最大流大部分解法原理,增广路定理:只要存在增广路,流就可以继续增大。证明显而易见,这里省去其实是我不会证。运用这一定理的算法有多种,这里只介绍最常见的Dinic算法。Dinic的原理可以概括为“层次图”和“阻塞流”,即不断使用bfs构造出层次图,在层次图中每一层多路增广,卡掉小边,最后从源点到不了汇点的时候流的大小即为最大流。图中最多有n层,会扩展n次,每次扩展中有n个节点搜索,进退流m次,因此单次增广时间复杂度为$O(nm)$,总的时间复杂度上限为$O(n^2m)$,实际上远没有这么差,如果是二分图匹配这种情况,甚至可以证(chui)明(bi)出时间复杂度为$O(\sqrt{n}m)$,浮动太大,因此接下来我们将不再讨论时间复杂度问题明明是你太蒻讨论不了啊喂,只认为时间复杂度有两种可能:$O(能过)$、$O(不能过)$。直接贴板子。

技术分享
 1 int S,T;
 2 int f[maxn][maxn],num[maxn][maxn],cnt,dist[maxm];
 3 int flag[maxn][maxn];
 4 bool bfs()
 5 {
 6     memset(dist,-1,sizeof(dist));
 7     dist[S]=1;
 8     queue<int>q;q.push(S);
 9     while(!q.empty())
10     {
11         int t=q.front();q.pop();
12         for(int i=head[t];i!=-1;i=edge[i].next)
13         {
14             int v=edge[i].to;
15             if(edge[i].flow>0&&dist[v]<0)
16             {
17                 dist[v]=dist[t]+1;
18                 q.push(v);
19                 if(v==T)return 1;
20             }
21         }
22     }
23     return 0;
24 }
25 int dfs(int pos,int flow)
26 {
27     if(pos==T)return flow;
28     for(int i=head[pos];i!=-1;i=edge[i].next)
29     {
30         int v=edge[i].to;
31         if(dist[pos]+1==dist[v]&&edge[i].flow>0)
32         {
33             int t=dfs(v,min(flow,edge[i].flow));
34             if(t>0)
35             {
36                 edge[i].flow-=t;
37                 edge[i^1].flow+=t;
38                 return t;
39             }
40         }
41     }
42     return 0;
43 }
44 int Dinic()
45 {
46     int ans=0,cnt;
47     while(bfs())
48            while(cnt=dfs(S,inf))ans+=cnt;
49     return ans;
50 }
板子

接下来我们继续口胡来看最小割,对于最小割有最小割定理:最小割=最大流。证明如下:

开始Ctrl+C @assassainPPT

证明:对于一个割来说,所有从s到t的流量必定经过删除的边,那么Max_flow一定 ≤ 割的值,同理可以推出Max_flow ≤ 任意割的值。
下面来看一个已经跑完最大流的残余网络,此时图中已没有从s到t的路径。将s和s能到达的所有点划分为S集,剩余点为T集。中间的所有边为一个割且均满载(剩余容量为0),那么当前流也就是最大流等于割的值,又因割的值大于等于最大流,所以此时的割即为最小割,且与最大流相等。

Ctrl+C完啦

最后我们来看玄学之王费用流。通过最大流定理我们可以知道找增广路就可以得到最大流,那么我们只要在找增广路时贪心找到单位流量费用最小增广路即可。这个证明比较简单,留给读者思考。你又不会了是不是啊。根据思(chang)考(shi),我们可以发现SPFA的时间复杂度比较小,可以保留在Dinic接近$O(不能过)$时过掉的希望。然而SPFA自己的时间复杂度也是$O(玄学)$的,因此,费用流的时间复杂度更加难以预测,大多数时间只能看情况考虑赌脸。

(证明自己是个欧洲人的机会来了)

板子嘛……还没打……留坑待填(逃

今天大概就是这样,如果还有什么新的体会我会继续更新然而你不是哪篇最后都没更新完成……

【您有新的未分配天赋点】网络流:从懵逼到完全懵逼

标签:重要   通过   比较   最大流   最小   删除   eof   pre   nic   

原文地址:http://www.cnblogs.com/Loser-of-Life/p/7257361.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!