【不定期更新篇(未成形篇)】

一直在搞,就像吃很恶习的东西,好想吐;

但还是可以理解成良药苦口啊~;

基础知识定义:

网络是一种特殊的有向图。

有向加权图G,指定两个定点S和T,分别称为源和汇。边上的权值称为容量;

网络中的一个可行流并不是改路线中所有边的容量的简单相加,这段路线的总承重量受路线中最小容量边的制约。

寻找方案使得总运输量最大,这就是网络流算法需要解决的问题;

通俗的讲:(我将说路就是管道,路的权值就是管道的容量)

在一个网络中,往源点灌水,然后从源点水开始流向汇点,

【只考虑在单位时间下】

1.如果从大的流分流,分开的流的总和是小于这个流的,那么支流的流量就是本身的容量,见下图(1);

2.如果从小的流往大的容量的管道,那么对于大的管道来说,水流过来才这么点,所以大的管道也才只有之前的那么多水而已啊,见图(2);

一个网络中的最大流就是指该网络中流值最大的流,只是指了某条特定的流,而我们是要通过方法来计算这个最大流的流值是多大。

感觉先搞一下网络流算法EK算法的流程好像还是不懂,真的好无力啊。

可以先打一遍!!!(推荐);

大致流程就是BFS一下,找到一条增广路,搞出一个最小的流值,从源到汇上的路的权值减去这个流值,并且在汇到源上权值加上这个流值;

FF方法的具体步骤(摘自图论书):

(1):初始化网络中所有边的容量,c<u,v>继承该边的容量,c<v,u>初始化为0,其中边<v,u>即为回退边。初始化最大流为0;

(2):在残留网络中找出一条从源S到汇T的增广路p。如果能找到,则转步骤(3);

如不能找到,则转步骤(5).

(3):在增广路p中找出所谓的“瓶颈”边,即路径中容量最小的边,记录下这个值X,并且累加到最大流中,转步骤(4)。

(4):将增广路中所有c< u , v >减去X,所有c<v,u>加上X,构成新的残留网络。转步骤(2).

(5):得到网络的最大流,退出。

const intN=110;      //最大点个数
intma[N][N],n,p[N];  //ma:邻接数组;n:点数;p:前驱数组
bool EK_bfs()
{queue<int>q;//队列
bool flag[N];//标记数组
//初始化memset(flag,false,sizeof(flag));memset(p,-1,sizeof(p));while(!q.empty())q.pop();flag[1]=true;q.push(1);while(!q.empty()){int u=q.front();q.pop();if(u==m)        //当队列弹出的点为终点时即可判增广路已经找到;return true;for(int i=1;i<=m;i++){if(ma[u][i]&&!flag[i])//当边容量非0,且增广点未标记{flag[i]=true;p[i]=u;        //记录前驱q.push(i);}}}return false;
}int EK()
{int u,ans=0,mm;while(EK_bfs())//当增广成功的时候{mm=INF;u=m;while(p[u]!=-1){mm=min(mm,ma[p[u]][u]);u=p[u];     //寻找到“瓶颈”边,并且记录容量(也可以在BFS过程中求出)}ans+=mm;  //累加进最大流u=m;while(p[u]!=-1) //修改路径上边的容量;{ma[p[u]][u]-=mm;ma[u][p[u]]+=mm;u=p[u];          }}return ans;
}

感觉打完了一发。。。还是好难理解是不是,模拟一发吧。。。

原题链接(http://poj.org/problem?id=1273)

给你4个点,5条边;

5 4
1 2 40//代表1到2有40的容量
1 4 20
2 4 20
2 3 30
3 4 10
然后模拟(我就记录个flow的结果,细节上的自行模拟了…)
一开始进去:
初始化,
从源 1 开始,
1->2,flow[2]=40;  2入队;
1->4,flow[4]=20;  4入队;
2->3,flow[3]=min(flow[2],ma[2][3])=20;
2->4,不需要,4已经处理过了
4出队=汇点,返回;
然后回溯一下:找到一个最小的流,然后更新,将找到的增广路把这个残留网络额外的流减去,反向边加上这个值
……
一直循环到找不到增广路为止;
 

可惜。。。真心好难理解啊。。打完还是似懂非懂,其实最重要的两步就是BFS找增广路,然后构造一下残留网路,一直循环,然后直到找不到增广路,当前的流值,就是最大流;

然后理解Dinic算法,推荐:Comzyh的博客

基本流程:

1.根据残留网络计算层次图;

2.在层次图中使用DFS进行增广直到不存在增广路

3.重复以上步骤直到无法增广

--------补充说明一个找增广的问题;

给出这样一副图:

先找到的增广有:

路      流量     转化成    路   流量    路   流量

1->2     2                    1<-2    2      1->2   0

2->4     2                    4<-2    2      2->4   0

4->6     2                    6<-4    2      4->6   0

ok,这样就是找到一个完全的增广;ans+=2;

继续;

1->3     1                    3<-1    1     1->3   0

3->4     1                    4<-3    1     3->4   0

4->2     2                    2->4    1     4->2   1

2->5     1                    5->2    1     2->5   0

5->6     1                    6->5    1     5->6   0

ok,又是一个增广 ;ans+=1;

终点阐述反向弧的作用:

反向弧可以理解我给这条路分配了x的流量,我建立一个反向弧,等下给自己一个后悔的机会。

比如上面那个第一次找增广过程中4->2建立反向弧,在第二次找增广的时候利用了这个反向弧;

我们可以理解之前我先安排2单位水通过这条路,不要理解成是这条路给的流量,流量都是从源点出发的,很自然这条路上的流量是上面那条路的流量流过来。

对于第一次,留多少呢,我先流个2吧,然后给自己一个机会(建立一个反向弧),等会可能我往这个方向不流2,比如第二次找到了,我可以去别的方向流1,那多个机会流还不好啊,形象上的理解就是上面那个点出来的分流了;

那么还有一个问题,怎么理解反向弧前面的那些路呢?

 是不是可以理解这条路(3->4)的流能到达路(2->4)到达4这个点,然而4以后已经阻断了,或者说已经塞了一部分流量了,

然后呢可以利用路(2->4)的反向弧(4->2),索取一部分他的,后悔以后就是说前面那个点(2)在这里分流了,注意每次找的增广都是一个能实现的图上的一个"瓶颈",

然后点(2)分流,实际上是给路(2->5)1单位,给路(2->4)1单位,然后路(3->4)往点4运了1单位,4->6流向6就是2单位;

贴一发DINIC的模板;

邻接矩阵版本:

const int INF=0x3f3f3f3f;
const int N=1e3+10;int ma[N][N];
int dis[N];
int q[N*100],h,r;
int n,m,ans;bool BFS()
{int i,j;memset(dis,-1,sizeof(dis));dis[1]=0;h=0,r=1;q[1]=1;while(h<r){j=q[++h];for(i=1;i<=n;i++){if(dis[i]<0&&ma[j][i]>0){dis[i]=dis[j]+1;q[++r]=i;}}}if(dis[n]>0)return true;return false;
}int DFS(int x,int low)
{int i,a=0;if(x==n)return low;for(int i=1;i<=n;i++){if(ma[x][i]>0&&dis[i]==dis[x]+1&&(a=DFS(i,min(low,ma[x][i])))){ma[x][i]-=a;ma[i][x]+=a;return a;}}return 0;
}void DINIC()
{int tans;ans=0;while(BFS()){while(tans=DFS(1,INF))ans+=tans;}printf("%d\n",ans);
}

前向星版本:HDU(3549)

#include<bits/stdc++.h>
using namespace std;
typedef __int64 LL;const int INF=0x3f3f3f3f;
const int N=2050;int level[N];
int q[N],h;
int n,m,ans;struct asd{int to;int w;int next;
};
asd edge[2500000];
int head[2500000],tol;bool BFS(int s,int t)
{int i,k;int top;memset(level,0,sizeof(level));level[s]=1;h=0;q[h++]=s;for(int i=0;i<h;i++){top=q[i];if(top==t)return true;for(k=head[top];k!=-1;k=edge[k].next){if(!level[edge[k].to]&&edge[k].w>0){q[h++]=edge[k].to;level[edge[k].to]=level[top]+1;}}}return false;
}int DFS(int now,int maxw,int t)
{int w,k,ret=0;if(now==t)return maxw;for(k=head[now];k!=-1;k=edge[k].next){if(edge[k].w>0&&level[edge[k].to]==level[now]+1){w=DFS(edge[k].to,min(maxw-ret,edge[k].w),t);edge[k].w-=w;edge[k^1].w+=w;ret+=w;if(ret==maxw)return ret;}}return ret;
}void DINIC()
{ans=0;while(BFS(1,n))ans+=DFS(1,INF,n);printf("%d\n",ans);
}void add(int a,int b,int c)
{edge[tol].w=c;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
}int main()
{int T,cas=1;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);int u,v,x;tol=0;memset(head,-1,sizeof(head));for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&x);add(u,v,x);add(v,u,0);}printf("Case %d: ",cas++);DINIC();}return 0;
}

后悔的就是原来分流,新流往原来的路走。。。

好好理解吧。。。。

也求一个好理解的idea!

转载于:https://www.cnblogs.com/keyboarder-zsq/p/6216804.html

萌新瞎讲网络流之最大流【不定期更新理解篇】相关推荐

  1. 萌新带你开车上p站(番外篇)

    前言 这道题目应该是pwnable.kr上Toddler's Bottle最难的题目了,涉及到相对比较难的堆利用的问题,所以拿出来分析. 登录 看看源程序 程序中有几点要注意的地方: 1. 定义的OB ...

  2. html 和jsp 引入jquery_不用jsp怎么实现前后端交互?给萌新后端的ajax教程(1)

    众所周知jsp是已经入土的技术,虽然仍有不少老项目在用,但已经不值得花时间学习了,当然了解一下也是可以的.如果你是一位萌新后端,不想了解jsp,或者想做一个前后端分离的项目,想在纯html网页上实现前 ...

  3. 姬魔恋战纪送衣服显示服务器繁忙,姬魔恋战纪新手有哪些问题-姬魔恋战纪萌新常见问题汇总_手心游戏...

    姬魔恋战纪新手有哪些问题?姬魔恋战纪萌新常见问题汇总.在游戏中萌新们总会遇见各种各样的问题(听说这游戏没有萌新全是大佬orz),一起来看看这篇姬魔恋战纪萌新常见问题汇总吧. 姬魔恋战纪萌新常见问题汇总 ...

  4. 网络流题目详讲+题单(提高版)(持续更新中......)

    网络流题目详讲+题单(提高版)(持续更新中......) 标签:图论--网络流 PS:如果你觉得自己还不够强(和我一样弱),可以去入门版看看 阅读体验:https://zybuluo.com/Junl ...

  5. 给萌新HTML5 入门指南

    HTML5的发展改变了互联网技术趋势,前端热度依旧不减,所以对于应用开发人员前端技术也成了必备技能之一,本篇文章的目的是为了帮助萌新的入门指导,也同时希望能为老鸟起到一定查漏补缺的作用,那么让我们开始 ...

  6. 飞猪登录器推荐《怪物猎人世界》萌新入坑武器装备推荐

    飞猪IP,地址修改器官网 http://www.feizhujsq.com/ 飞猪ip登录器致力于解决互联网延迟,为让中国玩家畅玩海内外优秀游戏(Steam/Origin/Uplay/PS/XBOX等 ...

  7. (萌新笔记)C++与C的不同

    本文设计到的C++知识比较浅薄,只适用于学过一些C语言并想大致看看C++的伙伴 一.引入概念字面量(我知道C语言有,但我那时还没学 定义:字面量(literal)是用于表达源代码中一个固定值的表示法( ...

  8. ubuntu16.04系统安装新手家萌新指南全图步骤

    ubuntu16.04系统安装新手指南 第一步:下载ubuntu 16.04.5 LTS 安装理由 下载ubuntu镜像文件 第二步:刻录镜像制作U盘为启动盘 刻录准备 开始制作启动盘 第三步:删除多 ...

  9. python手机版做小游戏代码大全-Python大牛手把手教你做一个小游戏,萌新福利!...

    原标题:Python大牛手把手教你做一个小游戏,萌新福利! 引言 最近python语言大火,除了在科学计算领域python有用武之地之外,在游戏.后台等方面,python也大放异彩,本篇博文将按照正规 ...

最新文章

  1. Windows下配置Chrome WebDriver
  2. confd_confd + Nacos | 无代码侵入的配置变更管理
  3. 一个问题让我直接闭门思过!!!拼多多面试必问项之List实现类:LinkedList
  4. C语言没有引用,只有指针
  5. 【渝粤教育】电大中专新媒体营销实务 (3)作业 题库
  6. python数据结构与算法
  7. 华为nova9 SE官网上架:华为首款1亿像素手机
  8. Spring系统学习:20180612--aop配置中表达式的写法
  9. sed shell 替换空格_shell三剑客之sed!
  10. tcpdump高级过滤
  11. 自豪地采用WordPress,如何删除链接?
  12. 如何把软件Origin切换变成中文显示?
  13. Windows 域时间同步
  14. sqldblink建好不能查询_眉山这个停车场显示有车位却不能停?原来是……
  15. 计算机的绝密历史——窃取的创意、专利战争和丑闻如何改变了世界……
  16. 三、kylin读写分离集群部署
  17. soundwire修改服务器,SoundWire Server,电脑声音实时同步到移动手机
  18. 什么是时序数据?如何治理?
  19. 树叶飘落、雪花飘落等同时多个图片飘落
  20. 企业微信oauth认证_微信企业号OAuth2验证接口实例(使用SpringMVC)

热门文章

  1. c语言不用math就算次方,C语言中math.h定义了哪些函数
  2. 【深度】关于互联网广告的思考
  3. 存储:lun与卷(LVM)
  4. 山东计算机一级选择题,计算机一级考试试题选择题(完整)
  5. MYSQL修改密码(附报错解决方案)
  6. NXP蓝牙电话ECNR算法简介
  7. note-linux:无法远程连接到服务器
  8. iterm2 字体颜色
  9. SpringBoot+Linux操作系统与项目部署(这一篇就够了|超详细)
  10. IDEA中spring框架快速搭建