zoukankan      html  css  js  c++  java
  • 【LOJ117】有源汇有上下界最小流

    点此看题面

    • 有一张(n)个点(m)条边的图。
    • 给你每条边的流量上下界,让你先判断是否存在可行流,若存在则求出从(s)(t)的最小流。
    • (nle50003,mle125003)

    算是对有源汇网络流的一个复习吧,也不知道为什么之前刷板子的时候会把这道漏了。。。

    有源汇网络流

    有源汇有上下界最大流类似,我们先从汇点向源点连一条下界为(0)、上界为(INF)的边(相当于是使原本不满足流量平衡的源汇点也能满足流量平衡,转化成普通点,消去了所谓源汇),跑一遍无源汇有上下界可行流

    然后我们记录下添上的这条辅助边的流量并把它删去,就得到了此时可行流中源点到汇点的流量。(有源汇有上下界最大流其实也有这个操作,只不过是直接放在最大流中一起跑了)

    想要求出最小流,可以从源点向汇点跑网络流来实现退流,用记下的可行流流量减去退流退掉的流量就是答案了。

    代码:(O(Dinic))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Rg register
    #define RI Rg int
    #define Cn const
    #define CI Cn int&
    #define I inline
    #define W while
    #define N 50003
    #define M 125003
    #define LL long long
    #define INF (LL)1e18
    using namespace std;
    int n,m,s,t;
    namespace D
    {
    	#define ss (n+1)
    	#define tt (n+2)
    	#define adde(x,y,f) (add(x,y,f),add(y,x,0)) 
    	#define add(x,y,f) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].F=f)
    	#define del(x) (lnk[x]=e[lnk[x]].nxt)
    	int ee=1,lnk[N+5],cur[N+5];struct edge {int to,nxt;LL F;}e[2*(N+M)+5];
    	int q[N+5],d[N+5];I bool BFS(CI s,CI t) {RI i,k,H,T;for(i=1;i<=tt;++i) d[i]=0;d[q[H=T=1]=s]=1;
    		W(H<=T) for(i=lnk[k=q[H++]];i;i=e[i].nxt) e[i].F&&!d[e[i].to]&&(d[q[++T]=e[i].to]=d[k]+1);return d[t];}
    	I LL DFS(CI x,CI t,LL f=INF) {if(x==t||!f) return f;LL o,g=0;for(RI& i=cur[x];i;i=e[i].nxt)
    		if(d[e[i].to]==d[x]+1&&(o=DFS(e[i].to,t,min(f,e[i].F)))&&(e[i].F-=o,e[i^1].F+=o,g+=o,!(f-=o))) break;return g;}
    	LL w[N+5];I void Add(CI x,CI y,Cn LL& l,Cn LL& u) {adde(x,y,u-l),w[x]+=l,w[y]-=l;}//从x向y连一条下界l、上界u的边
    	I bool Flow() {RI i;for(i=1;i<=n;++i) w[i]>0&&adde(i,tt,w[i]),w[i]<0&&adde(ss,i,-w[i]);D::Add(t,s,0,INF);//每个点根据供需与超级源汇连边;汇点向源点连辅助边
    		W(BFS(ss,tt)) memcpy(cur,lnk,sizeof(lnk)),DFS(ss,tt);for(i=lnk[ss];i;i=e[i].nxt) if(e[i].F) return 0;return 1;}//超级源向超级汇跑最大流,检验是否流满
    	I LL MinFlow() {LL g=e[lnk[s]].F;del(s),del(t);W(BFS(t,s)) memcpy(cur,lnk,sizeof(lnk)),g-=DFS(t,s);return g;}//记下辅助边流量并把它删去,从源点向汇点退流
    }
    int main()
    {
    	RI i,x,y,l,u;for(scanf("%d%d%d%d",&n,&m,&s,&t),i=1;i<=m;++i) scanf("%d%d%d%d",&x,&y,&l,&u),D::Add(x,y,l,u);
    	return D::Flow()?printf("%lld
    ",D::MinFlow()):puts("please go home to sleep"),0;//判断是否存在可行流,然后求最小流
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    [APIO 2009] Atm
    Codeforces518 D. Ilya and Escalator
    [POJ2096] Collecting bugs
    [ZOJ3329] One Person Game
    [LightOJ1038] Race to 1 Again
    「NOI2003」逃学的小孩
    [HAOI2006] 旅行
    ☆ [POJ2411] Mondriaan's Dream 「状压DP」
    「POJ3311」Hie with the Pie
    「乘法逆元」 学习笔记
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ117.html
Copyright © 2011-2022 走看看