1. 程式人生 > >[學習筆記] 上下界網路流學習筆記

[學習筆記] 上下界網路流學習筆記

帶下界的流建圖如下:
對於<u,v,down,up>,新建超級源點S’和超級匯點T’,連<S’,v,down>,<u,T’,down>,<u,v,up-down>
無源匯可行流:
直接判是否滿流即可。
有源匯最小流:
連<T,S,INF>,然後跑完F(S’,T’)的網路跑F(S,T)就是答案(不要刪去<T,S>這條邊)
有源匯最大流:
連<T,S,INF>,然後跑完F(S’,T’)的網路上,記錄<T,S>的流量x,刪去<T,S>及其反向邊,然後用x減去F(T,S)即可(最大的退流)。
loj #116 : 有源匯最小流:

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define N 100010
#define M 100010
#define INF (INT_MAX/2-10)
#define debug(x) cerr<<#x<<"="<<x #define sp <<" " #define ln <<endl using namespace std; typedef pair<int,int> pii; typedef set<int>::iterator sit; inline int inn() { int x,ch;while((ch=gc)<'0'||ch>'9'); x=ch^'0';while((ch=gc)>='0'&&ch<=
'9') x=(x<<1)+(x<<3)+(ch^'0');return x; } struct edges{ int to,pre,resf; }e[M];int h[N],etop,lev[N],cur[N],frms[N];queue<int> q; inline int add_edge(int u,int v,int f) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop,e[etop].resf=f; } inline int build_edge(int u,int v,int f) { return add_edge(u,v,f),add_edge(v,u,0); } inline int build_edge(int u,int v,int lw,int up) { return frms[v]+=lw,frms[u]-=lw,build_edge(u,v,up-lw); } inline bool bfs(int s,int t,int n) { memset(lev,0,sizeof(int)*(n+1)); while(!q.empty()) q.pop();q.push(s),lev[s]=1; while(!q.empty()) { int x=q.front();q.pop(); for(int i=h[x],y;i;i=e[i].pre) if(e[i].resf&&!lev[y=e[i].to]) lev[y]=lev[x]+1,q.push(y); } return lev[t]>0; } int dfs(int s,int t,int a) { if(s==t||!a) return a;int flow=0,f; for(int &i=cur[s];i;i=e[i].pre) if(lev[e[i].to]==lev[s]+1&&(f=dfs(e[i].to,t,min(a,e[i].resf)))>0) { e[i].resf-=f,e[((i-1)^1)+1].resf+=f,a-=f,flow+=f;if(!a) break; } return flow; } inline int dinic(int s,int t,int n,int flow=0) { while(bfs(s,t,n)) memcpy(cur,h,sizeof(int)*(n+1)),flow+=dfs(s,t,INF);return flow; } int main() { int n=inn(),m=inn(),s=inn(),t=inn(); for(int i=1,x,y,l,u;i<=m;i++) x=inn(),y=inn(),l=inn(),u=inn(),build_edge(x,y,l,u); int ss=n+1,tt=n+2,tot=0; rep(i,1,n) if(frms[i]>0) build_edge(ss,i,frms[i]),tot+=frms[i]; else build_edge(i,tt,-frms[i]); build_edge(t,s,INF); if(dinic(ss,tt,tt)^tot) return !printf("please go home to sleep\n"); return !printf("%d\n",dinic(s,t,tt)); }

有源匯最大流:

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define N 1000010
#define M 1000010
#define INF (INT_MAX/2-10)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
	int to,pre,resf;
}e[M];int h[N],etop,lev[N],cur[N],frms[N];queue<int> q;
inline int add_edge(int u,int v,int f) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop,e[etop].resf=f; }
inline int build_edge(int u,int v,int f) { return add_edge(u,v,f),add_edge(v,u,0); }
inline int build_edge(int u,int v,int lw,int up) { return frms[v]+=lw,frms[u]-=lw,build_edge(u,v,up-lw); }
inline bool bfs(int s,int t,int n)
{
	memset(lev,0,sizeof(int)*(n+1));
	while(!q.empty()) q.pop();q.push(s),lev[s]=1;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=h[x],y;i;i=e[i].pre)
			if(e[i].resf&&!lev[y=e[i].to])
				lev[y]=lev[x]+1,q.push(y);
	}
	return lev[t]>0;
}
int dfs(int s,int t,int a)
{
	if(s==t||!a) return a;int flow=0,f;
	for(int &i=cur[s];i;i=e[i].pre)
		if(lev[e[i].to]==lev[s]+1&&(f=dfs(e[i].to,t,min(a,e[i].resf)))>0)
		{	e[i].resf-=f,e[((i-1)^1)+1].resf+=f,a-=f,flow+=f;if(!a) break;	}
	return flow;
}
inline int dinic(int s,int t,int n,int flow=0)
{	while(bfs(s,t,n)) memcpy(cur,h,sizeof(int)*(n+1)),flow+=dfs(s,t,INF);return flow;	}
int main()
{
	int n=inn(),m=inn(),s=inn(),t=inn();
	for(int i=1,x,y,l,u;i<=m;i++)
		x=inn(),y=inn(),l=inn(),u=inn(),build_edge(x,y,l,u);
	int ss=n+1,tt=n+2,tot=0;build_edge(t,s,INF);
	rep(i,1,n)
		if(frms[i]>0) build_edge(ss,i,frms[i]),tot+=frms[i];
		else build_edge(i,tt,-frms[i]);
	if(dinic(ss,tt,tt)^tot) return !printf("please go home to sleep\n");
	for(int i=h[t];i;i=e[i].pre) if(e[i].to==s)
		tot=INF-e[i].resf,e[i].resf=e[((i-1)^1)+1].resf=0;
	return !printf("%d\n",tot-dinic(t,s,tt));
}