1. 程式人生 > 其它 >【模板】網路最大流

【模板】網路最大流

link

終於過了這個奇怪的網路流了。一直感覺那個什麼Dinic演算法很奇怪,還要什麼bfs分層,今天花了一下午的時間終於搞懂了Dinic是什麼鬼。

Dinic是一個求解網路最大流的演算法。我目前所掌握的只是小優化版本的Dinic,至於資料加強版我過不了(太弱了)。這個演算法和前面二分圖最大匹配演算法是一個核心,都是在思考假如我們已經有一個方案了,如何在不破壞這個方案的基礎上儘量多地塞新的元素進去(新的元素就是所謂的增廣路)。二分圖上增廣路是一個交錯雜居的路徑,而網路流中的增廣路是一條從S到T的一個流量不為0的合法軌跡。如何求解?首先可以使用樸素的想法,假如我們已經有一個網路流了(或者叫做殘量網路流),思考如何能找尋一條增廣路呢?有兩種途徑。一是自己開闢一條新的道路通向匯點,另一種是讓其它道路的流量滾回去,空出來的流量自己填上。第一種很好思考,第二種應該怎麼辦呢?思考一下,對比一下新增這條增廣路前後這個網路的變化有哪些。很明顯原先那條被佔的路上的流量不會有變化,變化的是捱了打之後重新尋找出路的那股舊流開闢的道路罷了。既然變化量只有那個,那麼完全可以把這個過程看成是當前增廣路在開闢新天地,實現上只需要建反向邊就可以了。

講解裡那些術語把我搞蒙了,不就是那個意思嗎。

有個bfs對樸素演算法的優化。為什麼我不知道,但確實可以優化樸素的Dinic。另外這裡一定要手寫一個佇列,用std會死得很難看。程式碼層面,bfs很簡單不說,dfs就是枚舉出邊,驗證層數關係,累加流量即可。

#include<cstdio>
#include<cstring>
//#define zczc
#define int long long
using namespace std;
const int N=210;
const int M=5010;
const int inf=1e12;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline int min(int s1,int s2){
	return s1<s2?s1:s2;
}

int m,n,s,t;
struct edge{
	int t,v,next;
}e[M<<1];
int head[N],esum=1;
inline void add(int fr,int to,int val){
	esum++;e[esum].t=to;e[esum].v=val;e[esum].next=head[fr];
	head[fr]=esum;return;
}

int d[N],q[N],l,r;
bool bfs(){
	memset(d,0,sizeof(int)*(m+1));
	q[l=r=1]=s,d[s]=1;
	while(l<=r){
		int now=q[l++];
		for(int i=head[now],th;i;i=e[i].next){
			if(e[i].v&&d[th=e[i].t]==0)d[th]=d[now]+1,q[++r]=th;
		}
	}
	return d[t]>0;
}

int dfs(int wh,int val){
	if(wh==t)return val;int cost=0;
	for(int i=head[wh],th;i;i=e[i].next){
		if(e[i].v==0||d[th=e[i].t]!=d[wh]+1)continue;
		int now=dfs(th,min(val,e[i].v));
		e[i].v-=now,e[i^1].v+=now,val-=now,cost+=now;
	}
	return d[wh]=cost==0?0:d[wh],cost;
}

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	int s1,s2,s3;
	read(m);read(n);read(s);read(t);
	for(int i=1;i<=n;i++){
		read(s1);read(s2);read(s3);
		add(s1,s2,s3);add(s2,s1,0);
	}
	
	int ans=0;
	while(bfs())ans+=dfs(s,inf);
	printf("%lld",ans);
	
	return 0;
}
一如既往,萬事勝意