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;
    }
    
  • 相关阅读:
    2020中国最好大学排名.py(亲测有效)
    手机号码归属地的自动查询.py(亲测有效)
    网络图片的爬取和存储.py(亲测有效)
    百度360搜索关键词提交.py(亲测有效)
    亚马逊商品页面爬取(使用headers字段).py(亲测有效)
    淘宝商品页面的爬取.py(亲测有效)
    爬取网页的通用代码框架.py(亲测有效)
    匿名函数function前面的! ~等符号作用小解
    ng之自定义指令
    用nodejs搭建一个简单的服务监听程序
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/10213864.html
Copyright © 2011-2022 走看看