最小费用最大流

#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 cap,cost;

	edge(int _to,int _rev,ll _cap,ll _cost):to(_to),rev(_rev),cap(_cap),cost(_cost){};
};

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 cap,cost;
		cin >> u >> v >> cap >> cost;

		adj[u].emplace_back(v,0,cap,cost);
		adj[v].emplace_back(u,0,0,-cost);

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

	vector<ll> h(n+1,INF);	
	h[s] = 0;

	for (int tt=0;tt<n-1;tt++){
		bool ok = false;

		for (int u=1;u<=n;u++){
			if (h[u]==INF) continue;

			for (auto& [v,rev,cap,cost]:adj[u]){
				if (cap && h[u]+cost<h[v]){
					h[v] = h[u]+cost;
					ok = true;
				}
			}
		}

		if (!ok) break;
	}

	vector<ll> dis;

	auto dij = [&](){
		dis = vector<ll>(n+1,INF);
		dis[s] = 0;

		priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<>> pq;
		pq.emplace(0,s);

		while (!pq.empty()){
			auto [d,u] = pq.top();
			pq.pop();

			if (d>dis[u]) continue;

			for (auto& [v,rev,cap,cost]:adj[u]){
				if (cap && d+cost+h[u]-h[v]<dis[v]){
					dis[v] = d+cost+h[u]-h[v];
					pq.emplace(dis[v],v);
				}
			}			
		}

		return dis[t]!=INF;
	};

	vector<int> cur;

	//这里如果不使用vis数组会受到0费用边影响
	vector<bool> vis;

	ll res1=0,res2=0;

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

		ll sum = 0;
		int len = adj[u].size();
		vis[u] = true;

		for (int& i=cur[u];i<len;i++){
			auto& [v,rev,cap,cost] = adj[u][i];
			
			if (!vis[v] && cap && h[v]==h[u]+cost){
				ll f = dfs(v,min(mf,cap));

				cap -= f;
				adj[v][rev].cap += f;

				res2 += f*cost;

				mf -= f;
				sum += f;

				if (mf==0) break;
			}		
		}

		return sum;
	};

	while (dij()){
		cur = vector<int>(n+1,0);
		vis = vector<bool>(n+1,false);

		//注意要先更新h数组
		for (int i=1;i<=n;i++){
			if (h[i]!=INF && dis[i]!=INF){
				h[i] += dis[i];
			}
		}

		res1 += dfs(s,INF);
	}

	cout << res1 << ' ' << res2 << '\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:49  kzssCCC  阅读(3)  评论(0)    收藏  举报