zoukankan      html  css  js  c++  java
  • 网络流的几个小优化

    是不是觉得网络流的速度不尽人心?

    优化1

    优化1就是我们空间的优化,有时候我们打.other是不是打得心烦气燥?

    我们可以在初始化时len=1,那么以后要访问k的other时只需要k^1就可以了,简单来说就是二进制最后一位由1变0,由0变1。

    同时,有时候一条边的x也不大有用,所以我们一样可以省去,所以,这两个变量的省去让我们代码简洁易懂,又省空间,一举两得!


    优化2(弧优化)

    好了,当前弧优化是什么呢(虽然有些大佬自己推出了,但自己可能也不知道自己加了优化!)?

    根据最大流或zkw费用流(不会的可以点开我的博客,我已经置顶了),每次搜过的边基本上都是流不了的了,如果再去搜会十分浪费。

    那么,我们可以用一个数组保存每个点的搜到第几条边,每次用k慢慢跳到那跳边,再开始搜,同时,最后,再从第一条边开始搜到没搜的那条边的前一条,可以缩短一些时间!

    但是,每次慢慢跳太慢,可以直接记录是哪条边,嘿嘿嘿,就不用前面慢慢找了!

    当然,我给出最短的当前弧(最开始我打的那种长,但是稍稍快1ms左右QAQ,其实也差不了多少,还不如最短的好)。

    zkw流(只含递归部分,其他照旧,顺便说一下,MCMF加不了这个优化!):

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using  namespace  std;
    typedef  long  long  ll;
    struct  node
    {
        int  y,next;
        ll  c,k;
    }a[201000];int  last[1000],len=1;
    long  long  d[1100];
    bool  v[1100];
    int  n,m,st,ed;
    ll  cost=0;
    int  cur[1100];
    inline void  ins(int  x,int  y,ll  c,ll  k)
    {
        len++;
        a[len].y=y;a[len].c=c;a[len].k=k;
        a[len].next=last[x];last[x]=len;
        len++;
        a[len].y=x;a[len].c=0;a[len].k=-k;
        a[len].next=last[y];last[y]=len;
    }
    int  list[1100],head,tail;/*队列*/
    inline  bool  spfa()
    {
        memset(v,false,sizeof(v));v[ed]=true;/*判断是否进入队列*/
        memset(d,10,sizeof(d));d[ed]=0;/*从终点到这里要多少费用*/
        head=1;tail=2;list[head]=ed;/*从终点出发*/
        ll  inf=d[st];
        while(head!=tail)
        {
            int  x=list[head];
            for(int  k=last[x];k;k=a[k].next)
            {
    			int  y=a[k].y,kl=k^1;
                if(a[kl].c>0/*由于是倒着搜的,所以边也要反向边*/  &&  a[kl].k+d[x]<d[y])/*判断边是否可行并更新*/
                {
                    d[y]=a[kl].k+d[x];/*更新*/
                    if(v[y]==false)
                    {
                        v[y]=true;
    					list[tail++]=y;if(tail==n+1)tail=1;
                    }
                }
            }
            head++;
            if(head==n+1)head=1;
            v[x]=false;
        }
        return  d[st]!=inf;/*返回bool值*/
    }
    inline  ll  mymin(ll  x,ll  y){return  x<y?x:y;}/*找最小值*/
    long  long  find(int  x,ll  f)
    {
        if(x==ed)return  f;
        v[x]=true;
        ll  ans=0,t=0;
        for(int  k=cur[x];k;k=a[k].next)
        {
            int  y=a[k].y;
            if(v[y]==false/*这个点没走过才可以走,否则更新边的流量是会Balabala*/  &&  a[k].c>0  &&  d[x]-a[k].k==d[y])
            {
                ans+=t=find(y,mymin(a[k].c,f-ans));/*是不是很眼熟?*/
                a[k].c-=t;a[k^1].c+=t;cost+=t*a[k].k;
    			cur[x]=k;//这个很重要,cur[x]要在if里面更新!否则会拖延时间 
    			if(ans==f){v[x]=false;return  ans;}
            }
    	}
        v[x]=false;
        return  ans;/*妥妥的像最大流*/
    }
    int  main()
    {
        scanf("%d%d",&n,&m);
        st=1;ed=n;
        for(int  i=1;i<=m;i++)
        {
            int  x,y;
            ll  z,l;
            scanf("%d%d%lld%lld",&x,&y,&z,&l);
            ins(x,y,z,l);
        }
        ll  zans=0;
        while(spfa()==true)/*建图完成!*/
        {
        	memcpy(cur+1,last+1,(n<<2));//部分拷贝 
            zans+=find(st,ll(999999999999999));/*多次查找,找出所有增光路哦*/
        }
        printf("%lld %lld",zans,cost);
        return  0;
    }
    

    最大流(Dinic):

    #include<cstdio>
    #include<cstring>
    using  namespace  std;
    struct  node
    {
    	int  y,c,next;
    }a[210000];int  last[11000],n,m,len=1/*用异或代替.other*/,st,ed;
    int  cur[11000];//当前弧 
    inline  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  h[11000],list[11000],head=1,tail=n;
    inline  bool  bt_()
    {
    	memset(h,0,sizeof(h));h[st]=1;
    	head=1;tail=2;list[1]=st;
    	while(head!=tail)
    	{
    		int  x=list[head];cur[x]=last[x];//别忘了初始化cur 
    		for(int  k=last[x];k;k=a[k].next)
    		{
    			int  y=a[k].y;
    			if(a[k].c>0  &&  h[y]==0)
    			{
    				list[tail++]=y;
    				h[y]=h[x]+1;
    			}
    		}
    		head++;
    	}
    	if(h[ed]>0)return  true;
    	else  return  false;
    }
    inline  int  mymin(int  x,int  y){return  x<y?x:y;}
    int  find(int  x,int  f)
    {
    	if(x==ed)return  f;
    	int  s=0,t;
    	for(int  k=cur[x];k;k=a[k].next)
    	{
    		int  y=a[k].y;
    		if(h[y]==h[x]+1  &&  a[k].c>0)
    		{
    			s+=(t=find(y,mymin(a[k].c,f-s)));
    			a[k].c-=t;a[k^1/*.other*/].c+=t;
    			cur[x]=k;//在里面更新很重要 
    			if(s==f)return  f;//满足就退出,这步也很重要 
    		}
    	}
    	if(s==0)h[x]=0;
    	return  s;
    }
    int  main()
    {
    	int  ans=0;
    	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);
    	}
    	while(bt_()==true)ans+=find(st,999999999);
    	printf("%d
    ",ans);
    	return  0;
    }
    
  • 相关阅读:
    sqlhelper使用指南
    大三学长带我学习JAVA。作业1. 第1讲.Java.SE入门、JDK的下载与安装、第一个Java程序、Java程序的编译与执行 大三学长带我学习JAVA。作业1.
    pku1201 Intervals
    hdu 1364 king
    pku 3268 Silver Cow Party
    pku 3169 Layout
    hdu 2680 Choose the best route
    hdu 2983
    pku 1716 Integer Intervals
    pku 2387 Til the Cows Come Home
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/10213864.html
Copyright © 2011-2022 走看看