zoukankan      html  css  js  c++  java
  • 【LOJ115】无源汇有上下界可行流(模板题)

    点此看题面

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

    大致思路

    首先,每条边既然有一个流量下界(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
    ",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;//求答案
    }
    
  • 相关阅读:
    WPF(ContentControl和ItemsControl)
    WPF(x:Key 使用)
    WPF(Binding集合对象数据源)
    WPF(x:Type的使用)
    WPF(初识DataTemplate)
    Asp.net 全局错误处理
    给年轻程序员的建议(转自csdn)
    在.net中未能用trycatch捕获到的异常处理(转载)
    c#语音读取文字
    IIS 7.0 和 IIS 7.5 中的 HTTP 状态代码
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ115.html
Copyright © 2011-2022 走看看