最小费用最大流(Primal-Dual 原始对偶算法+多路增广)
https://www.luogu.com.cn/problem/P3381
先做一次 \(spfa\) 求势能,然后重复 \(dijkstra\) 和 \(dfs\) 在残留网络中累加流量和费用。
\(dfs\) 需要用 \(vis\) 标记访问节点,防止受 \(0\) 费用边影响无限循环。
每轮 \(dfs\) 结束后,更新势能数组,具体就是 \(h_i\) 直接加上 \(dis_i\)。
代码
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 9e18;
void solve(){
int n,m,s,t;
cin >> n >> m >> s >> t;
vector<vector<array<int,4>>> adj(n+1);
auto add = [&](int u,int v,int w,int c){
adj[u].push_back({w,c,(int)adj[v].size(),v});
adj[v].push_back({0,-c,(int)adj[u].size()-1,u});
};
for (int i=0;i<m;i++){
int u,v,w,c;
cin >> u >> v >> w >> c;
add(u,v,w,c);
}
vector<ll> h(n+1);
vector<bool> vis(n+1,true);
queue<int> q;
for (int i=1;i<=n;i++){
q.push(i);
}
while (!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for (auto& [w,c,rev,v]:adj[u]){
if (w>0 && h[u]+c<h[v]){
h[v] = h[u]+c;
if (!vis[v]){
q.push(v);
vis[v] = true;
}
}
}
}
vector<int> cur;
vector<ll> dis;
auto dij = [&](){
dis = vector<ll>(n+1,INF);
priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<>> pq;
dis[s] = 0;
pq.emplace(0,s);
while (!pq.empty()){
auto [d,u] = pq.top();
pq.pop();
if (d>dis[u]) continue;
for (auto& [w,c,rev,v]:adj[u]){
if (w>0 && d+h[u]-h[v]+c<dis[v]){
dis[v] = d+h[u]-h[v]+c;
pq.emplace(dis[v],v);
}
}
}
return dis[t]!=INF;
};
ll mxf = 0;
ll cost = 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& [w,c,rev,v] = adj[u][i];
if (w>0 && !vis[v] && dis[u]+h[u]-h[v]+c==dis[v]){
ll f = dfs(v,min(mf,(ll)w));
mf -= f;
w -= f;
sum += f;
adj[v][rev][0] += f;
if (mf==0) break;
}
}
return sum;
};
while (dij()){
cur = vector<int>(n+1);
vis = vector<bool>(n+1,false);
ll f = dfs(s,INF);
mxf += f;
cost += (dis[t]-h[s]+h[t])*f;
for (int i=1;i<=n;i++){
if (dis[i]!=INF){
h[i] += dis[i];
}
}
}
cout << mxf << ' ' << cost << '\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号