• 【LOJ116】有源汇有上下界最大流(模板题)


    点此看题面

    大致题意: 给你每条边的流量上下界,让你先判断是否存在可行流。若存在,则输出最大流。

    无源汇上下界可行流

    在做此题之前,最好先去看看这道题目:【LOJ115】无源汇有上下界可行流

    大致思路

    首先,我们先跑一遍无源汇上下界可行流,同时判断是否有解。

    等会儿,这题是有源汇的,而刚才提到的可行流是无源汇的,怎么办?

    答:没关系!

    直接从汇点向源点连一条下界为(0)、上界为(INF)的边,然后再按无源汇上下界可行流的套路建虚拟源汇做即可。

    但还有个问题,这样跑出来的肯定不是最大流,那该怎么办?

    我们只需在跑完可行流之后的图上再跑遍最大流,就可求出答案了。

    代码

    #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 202
    #define M 9999
    #define min(x,y) ((x)<(y)?(x):(y))
    #define INF 1e9
    using namespace std;
    int n,m,s,t;
    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 UpperLowerMaxFlow_with_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+2,Lsz=N+M+1<<1;int ee,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(CI s,CI t)//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,CI t)//DFS统计流量
    		{
    			if(!(x^t)||!f) return f;RI i,p,res=0;
    			for(i=cur[x];i;i=e[i].nxt)
    			{
    				if(cur[x]=i,(dep[x]+1)^dep[e[i].to]||!(p=DFS(e[i].to,min(f,e[i].Cap),t))) continue;
    				if(e[i].Cap-=p,e[((i-1)^1)+1].Cap+=p,res+=p,!(f-=p)) break;
    			}return !res&&(dep[x]=-1),res;
    		}
    		I bool FeasibleFlow()//无源汇有上下界可行流
    		{
    			RI i;for(i=P(1);i<=P(n);++i) v[i]>0&&AddOneWayEdge(s,i,v[i]),v[i]<0&&AddOneWayEdge(i,t,-v[i]);
    			W(BFS(s,t)) DFS(s,INF,t);for(i=lnk[s];i;i=e[i].nxt) if(e[i].Cap) return false;return true;
    		}
    	public:
    		int s,t;I UpperLowerMaxFlow_with_ST() {s=1,t=2;}I int P(CI x) {return x+2;}
    		I void Add(CI x,CI y,CI Lower,CI Upper) {AddOneWayEdge(x,y,Upper-Lower),v[x]-=Lower,v[y]+=Lower;}
    		I void MaxFlow(CI S,CI T)//最大流
    		{
    			if(Add(T,S,0,INF),!FeasibleFlow()) return (void)(puts("please go home to sleep"));
    			RI res=0;W(BFS(S,T)) res+=DFS(S,INF,T);printf("%d",res);//求解并输出答案
    		}
    }V;
    int main()
    {
    	RI i,x,y,Lower,Upper;for(F.read(n,m,s,t),i=1;i<=m;++i) F.read(x,y,Lower,Upper),V.Add(V.P(x),V.P(y),Lower,Upper);//建边
    	return V.MaxFlow(V.P(s),V.P(t)),0;//求解答案
    }
    
  • 相关阅读:
    设计模式(十六):职责链模式
    设计模式(十五):状态模式
    设计模式(十四):命令模式
    设计模式(十三):模板模式
    设计模式(十二):观察者模式
    远程连接数据库常出现的错误解析
    [解决] Error Code: 1044. Access denied for user 'root'@'%' to database
    linux常用命令
    linux上svn项目管理,同步服务器,用户管理
    linux 磁盘分区
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ116.html
Copyright © 2020-2023  润新知