ISAP学习笔记
学完了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学习笔记的更多相关文章
- js学习笔记:webpack基础入门(一)
		之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ... 
- PHP-自定义模板-学习笔记
		1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ... 
- PHP-会员登录与注册例子解析-学习笔记
		1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ... 
- 2014年暑假c#学习笔记目录
		2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ... 
- JAVA GUI编程学习笔记目录
		2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ... 
- seaJs学习笔记2 – seaJs组建库的使用
		原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ... 
- CSS学习笔记
		CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ... 
- HTML学习笔记
		HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ... 
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
		今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ... 
随机推荐
- VMWARE里安装时出现'SMBus Host Controller not enabled'
			在虚拟机上运行Linux内核版本为4.7或以上的系统都在安装过程中或在启动时会因为加载intel_powerclamp驱动而导致崩溃.解决办法:1.在启动Ubuntu的时候按住左Shift键:2.Ub ... 
- 一款可以安利的MarkDown编辑器
			Typeora一款可以安利的MarkDown编辑器 Typeora是什么?  一款使用MarkDown的本地编辑器集结了MarkDown的所有特点并展现了简洁.高效的特点,关键是免费. 特点: 支持 ... 
- Memory Leak Detection in Embedded Systems
			One of the problems with developing embedded systems is the detection of memory leaks; I've found th ... 
- shell-day1
			shell概述:这里说的是命令行shell,例如"bash/sh/ksh/csh"(Unix/Linux系统).cmd.exe命令提示字符(windwos系统),这里主要介绍Uni ... 
- markdown中设置、调整图片尺寸
			使用百分比描述尺寸 <img src="https://img2018.cnblogs.com/blog/1122471/201902/1122471-2019022218575673 ... 
- mangodb驱动编译
			1.Installing the MongoDB C Driver (libmongoc) and BSON library (libbson) Building on Windows with Vi ... 
- ojdbc14_g.jar与ojdbc14.jar区别
			在低级JDK版本1.2与1.3中使用的驱动,class12.jar,虽然实际上在1.4,1.5中使用大部分情况也是OK的 ojdbc14.jar (1,545,954 bytes) - classes ... 
- Intellij IDEA Organize Imports
			使用Eclipse进行开发时,我喜欢用Ctrl + Shift + O快捷键管理Java类的导入,它可以导入所需的Java类,去除不需要的Java类. Eclipse的Organize Imports ... 
- Django 玩转API
			现在,让我们进入Python的交互式shell,玩转这些Django提供给你的API. 使用如下命令来调用Python shell: $ python manage.py shell 我们使用上述命令 ... 
- MySQL理解索引、添加索引的原则
			索引用于快速找出在某个列中有一特定值的行.不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行,还需要考虑每次读入数据页的IO开销.而如果采取索引,则可以根据索引指向的页以及记录在 ... 
