ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【LOJ115】无源汇有上下界可行流(模板题)

2019-03-18 21:39:02  阅读:339  来源: 互联网

标签:upper lower 流量 下界 LOJ115 无源 初始 汇有 define


点此看题面

大致题意: 给你每条边的流量上下界,让你判断是否存在可行流。若有,则还需输出一个合法方案。

大致思路

首先,每条边既然有一个流量下界\(lower\),我们就强制它初始流量为\(lower\)。

而考虑到它还有一个流量上界\(upper\),其实这就等同于建一条初始流量为\(0\),而容量为\(upper-lower\)的边。

但考虑到流量平衡,因此我们可以考虑对于每个点用\(v_i\)记录下其流量的不平衡值,即对于一条边\(x->y\),我们将\(v_x\)减去\(lower\),将\(v_y\)加上\(lower\)。

在所有边加完后,对于所有\(v_i\)不等于\(0\)的点,如果\(v_i\)为正,则我们从源点向其连一条边权为\(v_i\)的边;如果\(v_i\)为负,则我们由其向汇点连一条边权为\(-v_i\)的边。

然后跑最大流。

如果能流满,就说明存在可行流,输出\(YES\),方案就是每条边当前流量加上其初始的下界\(lower\)

否则,输出\(NO\)。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200
#define M 10200
#define INF 1e9
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
int n,m;
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        char c,*A,*B,FI[FS];
    public:
        I FastIO() {A=B=FI;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
class UpperLowerFeasibleFlow_without_ST//无源汇有上下界可行流
{
    private:
        #define add(x,y,v) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].Cap=v)
        #define AddOneWayEdge(x,y,v) (add(x,y,v),add(y,x,0))
        static Con int Psz=N,Lsz=N+M<<1;int ee,iv[Lsz+5],lnk[Psz+5],cur[Psz+5],v[Psz+5],q[Psz+5],dep[Psz+5];
        struct edge {int to,nxt,Cap;}e[Lsz+5];
        I bool BFS()//BFS找增广路
        {
            RI i,k,H=1,T=1;memset(dep,0,sizeof(dep)),dep[q[1]=s]=1;W(H<=T&&!dep[t])
                for(i=lnk[k=q[H++]];i;i=e[i].nxt) e[i].Cap&&!dep[e[i].to]&&(dep[q[++T]=e[i].to]=dep[k]+1);
            return dep[t]?(memcpy(cur,lnk,sizeof(lnk)),true):false;
        }
        I int DFS(CI x,RI f)//DFS统计流量
        {
            if(!(x^t)||!f) return f;RI i,t,res=0;
            for(i=cur[x];i;i=e[i].nxt)
            {
                if(cur[x]=i,(dep[x]+1)^dep[e[i].to]||!(t=DFS(e[i].to,min(f,e[i].Cap)))) continue;
                if(e[i].Cap-=t,e[((i-1)^1)+1].Cap+=t,res+=t,!(f-=t)) break;
            }return !res&&(dep[x]=-1),res;
        }
    public:
        int s,t;I UpperLowerFeasibleFlow_without_ST() {s=1,t=2;}I int P(CI x) {return x+2;}
        I void Add(CI p,CI x,CI y,CI Lower,CI Upper) {iv[p]=Lower,AddOneWayEdge(x,y,Upper-Lower),v[x]-=Lower,v[y]+=Lower;}
        I void Build(CI n) {for(RI i=3;i<=n+2;++i) v[i]>0&&AddOneWayEdge(s,i,v[i]),v[i]<0&&AddOneWayEdge(i,t,-v[i]);}//对于所有v[i]不等于0的点进行连边操作
        I void FeasibleFlow()//求出一个可行流 
        {
            W(BFS()) DFS(s,INF);RI i;for(i=lnk[s];i;i=e[i].nxt) if(e[i].Cap) return (void)(puts("NO"));//如果没流满,输出NO
            for(puts("YES"),i=1;i<=m;++i) printf("%d\n",iv[i]+e[i<<1].Cap);//输出这条边的下界lower与它的流量的和
        }
}V;
int main()
{
    RI i,x,y,Lower,Upper;for(F.read(n,m),i=1;i<=m;++i) F.read(x,y,Lower,Upper),V.Add(i,V.P(x),V.P(y),Lower,Upper);//读入+建边
    return V.Build(n),V.FeasibleFlow(),0;//求答案
}

标签:upper,lower,流量,下界,LOJ115,无源,初始,汇有,define
来源: https://www.cnblogs.com/chenxiaoran666/p/LOJ115.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有