最大流 ($dinic$ 算法)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;

const ll INF = 9e18;

class edge{
public:
	int to,rev;
	ll c;

	//u->to 的反向边 to->u 是 adj[to][rev]
	edge(int _to,int _rev,ll _c):to(_to),rev(_rev),c(_c){};
};

void solve(){
	int n,m,s,t;
	cin >> n >> m >> s >> t;

	vector<vector<edge>> adj(n+1);
	for (int i=0;i<m;i++){
		int u,v;
		ll c;
		cin >> u >> v >> c;

		adj[u].emplace_back(v,0,c);
		adj[v].emplace_back(u,0,0);

		adj[u].back().rev = adj[v].size()-1;
		adj[v].back().rev = adj[u].size()-1;
	}

	//不需要初始化,每轮都会重置
	vector<int> cur,level;

	auto bfs = [&](){
		level = vector<int>(n+1,-1);

		queue<int> q;
		q.push(s);
		level[s] = 0;

		while (!q.empty()){
			int u = q.front();
			q.pop();

			for (auto& [v,rev,c]:adj[u]){
				if (level[v]!=-1 || c==0) continue;

				level[v] = level[u]+1;
				q.push(v);	
				if (v==t) return true;			
			}
		}

		return false;
	};

	function<ll(int,ll)> dfs = [&](int u,ll mf){
		if (u==t) return mf;
		ll sum = 0;

		int len = adj[u].size();

		//当前弧优化
		for (int& i=cur[u];i<len;i++){
			auto& [v,rev,c] = adj[u][i];

			if (level[v]!=level[u]+1 || c<=0) continue;

			ll f = dfs(v,min(mf,c));
			c -= f;
			adj[v][rev].c += f;

			sum += f;
			mf -= f;

			//剩余流量优化
			if (mf==0) break;
		}

		//残枝优化
		if (sum==0){
			level[u] = -1;
		}

		return sum;
	};

	ll res = 0;
	while (bfs()){
		cur = vector<int>(n+1,0);

		res += dfs(s,INF);
	}

	cout << res << '\n';
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int t = 1;
	// cin >> t;
	while (t--) solve();

	return 0;
}
posted @ 2026-04-14 00:48  kzssCCC  阅读(3)  评论(0)    收藏  举报