学完了ISAP,感觉心情舒畅,毕竟ISAP比Dinic好一点。

说到底ISAP其实是Dinic(不熟悉Dinic的人去我的博客找猴子课堂----最大流与最小割(看看思想),已经置顶)优化版,熟悉的人知道Dinic是通过不断分层来做的,但是,我们如果用打标记(貂蝉的标记)的方法就会快一些!

会快的原因就是因为他省了很多分层的时间,使得他比Dinic要快不少,首先,我们先初始化一遍(从t开始搜,建个分层图(不是说不用宽搜了吗)),虽然过程中不用多次分层,但初始化分层,使得代码要干的事情少了不少(因为让代码通过自身调整标记要O(n^2)时间,但如果用宽搜初始化分层就让时间缩短为O(n),也是十分不错的呢!)

然后每次按分层规矩(注意,这里以结尾为原点建分层图,是由高的层流向比他低一层的层)找一条路径(没错,你没听错,就是单路增广!),从起点出发:

流完后,然后回到起点,找另外一条流完,就结束了?



比如这张:

下面一条可行路径就因为———(儿童不宜)的关系流不过去了(分层有时会导致两个相邻点层数相同)。。。

所以,ISAP的精华!出来吧!

询问?询问什么?就是找与他相连的点(边要有流量)中层数最小的,之后,它就可以变身成比这个编号大一层的点(没有就为n+1),继续为流量做贡献!(在一个点找不到下一个点时,就调整这个点的标记)

改完之后:

就这样解决了呢!(只需要在s的层数大于点数就可以退出了)

呵呵

但是,我们仔细思考一下,标记其实是具有连续性的,因为你这个标记改了,你附近的标记也会随你+1或者走其他和你之前编号一样的点,所以每次+1就足够了,时间没多大差别,代码更短,何乐而不为?

断层优化:

当一个编号没有一个点,便可以结束,为什么?

我们可以知道,假设断层编号为x,那么起点大于x,容易知道,我们无法到达编号小于x的点,于是便可以结束。

然后,上!代码。。。

#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int y,c,next;
}a[210000];int len=1,last[21000],st,ed;
int num[21000],cur[21000],qian[21000],h[21000],n,m;
int mymin(int x,int y){return x<y?x:y;}
void ins(int x,int y,int c)
{
len++;
a[len].y=y;a[len].c=c;a[len].next=last[x];last[x]=len;
len++;
a[len].y=x;a[len].c=0;a[len].next=last[y];last[y]=len;
}
int list[21000],head,tail;
void bfs()
{
head=1;tail=2;list[head]=ed;h[ed]=1;num[1]++;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
if(h[a[k].y]==0 && a[k^1].c>0)
{
num[h[a[k].y]=h[x]+1]++;
list[tail++]=a[k].y;
}
}
head++;
}
if(h[st]==0)h[st]=n+1;
}
int add()
{
int now=ed,ans=999999999;
while(now!=st)
{
ans=mymin(ans,a[qian[now]].c);
now=a[qian[now]^1].y;
}
now=ed;
while(now!=st)
{
a[qian[now]].c-=ans;a[qian[now]^1].c+=ans;
now=a[qian[now]^1].y;
}
return ans;
}
int findflow()
{
int ans=0,now=st;
bfs();
while(h[st]<=n)
{
bool bk=true;
while(bk==true)
{
bk=false;
for(int k=cur[now];k;k=a[k].next)
{
if(a[k].c>0 && h[a[k].y]+1==h[now])
{
bk=true;
cur[now]=k;
now=a[k].y;
qian[now]=k;
break;
}
}
if(now==ed)
{
ans+=add();now=st;
}
}
if((--num[h[now]])==0)break;
num[++h[now]]++;cur[now]=last[now];
if(now!=st)now=a[qian[now]^1].y;
}
return ans;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&st,&ed);
for(int i=1;i<=m;i++)
{
int x,y,c;scanf("%d%d%d",&x,&y,&c);
ins(x,y,c);
}
for(int i=1;i<=n;i++)cur[i]=last[i];
printf("%d\n",findflow());
return 0;
}

为什么会快?

其实它比Dinic少了很多没用的递归,让每次找路径都有作用,而且用标记省了bfs的时间,所以,只要不被恶意卡掉,ISAP整体上比Dinic要优秀!

注:上面的图片侵权抱歉!

ISAP学习笔记的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

随机推荐

  1. gulp 前端构建工具入门

    gulp 前端构建工具入门 标签(空格分隔): gulp 1. 安装gulp npm i -g gulp 2. 创建gulp项目 2.1 Hello world 使用npm init初始化项目文件夹. ...

  2. oracle客户端plsql安装

    1.确认版本 自己的操作系统版本(32位还是64位),oracle instant client(oracle客户端版本)和plsql版本 我自己的版本是:oracle客户端版本 64位,plsql ...

  3. ADOBE READER把PDF转换成WORD教程

    目前国外很多软件的支持信息都使用PDF方式进行发布,如果没有Adobe  Reader,无法查看其内容,如果没有相关的编辑软件又无法编辑PDF文件.转换为DOC格式则可以实现编辑功能.尽管有些软件也可 ...

  4. AutoHotkey调用VBA实现批量精确筛选数据透视表某字段内容。

    如上图,想在数据透视表中只显示红色区域的内容,手动勾选就比较繁琐. 实现思路: 先复制红色的内容. 鼠标停留在数据透视表[型号]列的任意数据上(通过该单元格可以获取数据透视表和字段) 由于数据透视表的 ...

  5. yii2.0数据库查询修改等方法

    yii2.0学习有一段时间了,给大家分享一下一些简单的查询等如何操作. 查询:(这里最前面的Test是引用的模型名) Test::find()->all();    此方法返回所有数据: Tes ...

  6. Oracle RAC和SCAN同时对外提供服务的配制方法

    1,  tnsnames.ora on two nodes:RACTEST =  (DESCRIPTION =    (ADDRESS = (PROTOCOL = TCP)(HOST = racsca ...

  7. 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.3.垃圾收集器与内存分配策略

    1.学习目的 当需要排查各种内存溢出. 内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节. Java内存运行时区域的各个部分,其中程序计数 ...

  8. Go语言(二) 继承和重载

    继承 package main import "fmt" type Skills []string type person struct { name string age int ...

  9. 优秀的看图工具推荐 —— XnViewMP

    XnViewMP是一款非常棒的完全免费图片浏览器,支持100多种图片格式,XnViewMP还具有浏览器.幻灯片.屏幕捕捉.缩略图制作.批处理转换.十六进制浏览.拖放.通讯录.扫描输入等功能.XnVie ...

  10. U-Mail邮件群发如何过滤无效地址?

    U-Mail邮件群发平台可以自动过滤掉无效和重复地址,过滤效果如下图 U-Mail邮件群发平台会将客户已经确认好是无效地址的加入无效地址库,下次再导入改无效地址就直接拒绝.邮件格式不正确的也会直接过滤 ...