• 费用流处理负圈的方法


    以最小费用最大流为例,我们可以通过退流来消除费用为负数的边。
    具体过程:
    不妨设有一条从(u)(v)的容量为(c)费用为(d)的边((d<0))。
    先强制满流,把答案加上(c imes{d})
    之后,从(u)(T)(S)(v)各连一条容量为(c),费用为0的边,用来调整流量。这两条边要使用手段强制满流。
    最后,连一条从(v)(u)的容量为(c)费用为(-d)的边,用于退流。
    这样就没有负环了。

    也有解决负环的算法:

    此写法过慢,待修改

    正常,我们的最小费用流的费用都应该是正数。
    但是,有时,边权会出现负数,进而可能出现负圈。
    这时,我们可以这样处理:
    在每次增广时,先在整张图中找负圈,若能找到,则沿着负圈增广。
    否则,再找增广路进行增广。
    找负圈使用dfs的spfa会更好写,更快。
    可以优化:

    1. 每个点只搜索一次(见注释)。
    2. 如果搜不到负环了,就不需要再考虑负环了。

    代码:

    bool dfs(int u)
    {
    	bk[u]=true;
    	for(int i=fr[u];i!=-1;i=ne[i])
    	{
    		if(w[i]>0&&jl[u]+fy[i]<jl[v[i]])
    		{
    			jl[v[i]]=jl[u]+fy[i];
    			la[v[i]]=u;lb[v[i]]=i;
    			if(bk[v[i]])
    			{
    				fq=v[i];
    				return true;
    			}
    			if(dfs(v[i]))
    				return true;
    		}
    	}
    	bk[u]=false;
    	return false;
    }
    bool spfa()
    {
    	for(int i=1;i<=N;i++)
    	{
    		bk[i]=false;
    		jl[i]=inf;
    	}
    	for(int i=1;i<=N;i++)
    	{
    		fq=-1;
    		if(jl[i]==inf&&dfs(i))//每个点只搜索一次
    			return true;
    	}
    	for(int i=1;i<=N;i++)
    	{
    		bk[i]=false;
    		jl[i]=inf;
    	}
    	jl[S]=0;fq=-1;
    	dfs(S);
    	return jl[T]<inf;
    }
    int feiyl(int &fei)
    {
    	int he=0;fei=0;
    	while(spfa())
    	{
    		if(fq==-1)
    		{
    			int u=T,zx=inf;
    			while(u!=S)
    			{
    				if(w[lb[u]]<zx)
    					zx=w[lb[u]];
    				u=la[u];
    			}
    			he+=zx;fei+=jl[T]*zx;u=T;
    			while(u!=S)
    			{
    				w[lb[u]]-=zx;
    				w[lb[u]^1]+=zx;
    				u=la[u];
    			}
    		}
    		else
    		{
    			int u=fq,zx=inf;
    			while(1)
    			{
    				if(w[lb[u]]<zx)
    					zx=w[lb[u]];
    				u=la[u];
    				if(u==fq)break;
    			}u=fq;
    			while(1)
    			{
    				w[lb[u]]-=zx;
    				w[lb[u]^1]+=zx;
    				fei+=zx*fy[lb[u]];
    				u=la[u];
    				if(u==fq)break;
    			}
    		}
    	}
    	return he;
    }
    
  • 相关阅读:
    华为机试题01背包问题
    丑数
    动态规划(1)
    Linux 后台启动 Redis
    redis.exceptions.ResponseError: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk.
    SQLServer从渣仔到小白
    cmder 增强型命令行工具
    总结在部署分布式爬虫环境过程中常见的若干问题
    【pymongo.errors】Cursor not found
    浅析scrapy与scrapy_redis区别
  • 原文地址:https://www.cnblogs.com/lnzwz/p/12327725.html
Copyright © 2020-2023  润新知