最小费用最大流 和 最大流模板
Posted lifehappy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小费用最大流 和 最大流模板相关的知识,希望对你有一定的参考价值。
最大流
Edmond-Karp
原版的是用邻接矩阵写的,太耗内存了,这里改成邻接表。
#include <bits/stdc++.h>
using namespace std;
const int N1 = 1e4 + 10, N2 = 2e5 + 10;
const int INF = 0x3f3f3f3f;
int head[N1], to[N2], nex[N2], cap[N2], cnt;
int flow[N1], pre[N1], id[N1], n, m, s, t;
void add(int x, int y, int w) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = w;
head[x] = cnt++;
}
void input() {
scanf("%d %d %d %d", &n, &m, &s, &t);
int x, y, w;
for(int i = 0; i < m; i++) {
scanf("%d %d %d", &x, &y, &w);
add(x, y, w);
add(y, x, 0);
}
}
void init() {
memset(head, -1, sizeof head);
cnt = 0;
}
int max_flow() {
int ans = 0;
for(;;) {
queue<int> q;
memset(flow, 0, sizeof flow);
flow[s] = INF;
q.push(s);
while(!q.empty()) {
int temp = q.front();
q.pop();
for(int i = head[temp]; ~i; i = nex[i]) {
if(!flow[to[i]] && cap[i] > 0) {
flow[to[i]] = min(flow[temp], cap[i]);
pre[to[i]] = temp;
id[to[i]] = i;
q.push(to[i]);
}
}
if(flow[t]) break;
}
if(!flow[t]) break;
int p = t;
while(p != s) {
cap[id[p]] -= flow[t];
cap[id[p] + 1] += flow[t];
p = pre[p];
}
ans += flow[t];
}
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
init();
input();
printf("%d
", max_flow());
return 0;
}
Dinic
玄学的Dinic
#include <bits/stdc++.h>
using namespace std;
const int N1 = 1e4 + 10, N2 = 2e5 + 10;
const int INF = 0x3f3f3f3f;
int head[N1], to[N2], nex[N2], cap[N2], cnt;
int dis[N1], n, m, s, t;
void init() {
memset(head, -1, sizeof head);
cnt = 0;
}
void add(int x, int y, int w) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = w;
head[x] = cnt++;
}
bool bfs() {
memset(dis, -1, sizeof dis);
queue<int> q;
q.push(s);
dis[s] = 0;
while(!q.empty()) {
int temp = q.front();
q.pop();
if(temp == t) return true;
for(int i = head[temp]; ~i; i = nex[i]) {
if(dis[to[i]] == -1 && cap[i]) {
dis[to[i]] = dis[temp] + 1;
q.push(to[i]);
}
}
}
return false;
}
int dfs(int rt, int f) {
if(rt == t) return f;
int delta = f;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dis[to[i]] == dis[rt] + 1) {
int temp = dfs(to[i], min(delta, cap[i]));
cap[i] -= temp;
cap[i ^ 1] += temp;
delta -= temp;
}
if(delta == 0) break;
}
return f - delta;
}
int Dinic() {
int ans = 0;
while(bfs()) ans += dfs(s, INF);
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
init();
scanf("%d %d %d %d", &n, &m, &s, &t);
int x, y, w;
for(int i = 0; i < m; i++) {
scanf("%d %d %d", &x, &y, &w);
add(x, y, w);
add(y, x, 0);
}
printf("%d
", Dinic());
return 0;
}
最小费用最大流
SPFA
#include <bits/stdc++.h>
using namespace std;
const int N1 = 5e3 + 10, N2 = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int head[N1], to[N2], nex[N2], cap[N2], value[N2], cnt;
int dis[N1], pre[N1], id[N1], flow[N1], visit[N1], n, m, s, t;
void add(int x, int y, int f, int w) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
cap[cnt] = f;
head[x] = cnt++;
}
bool spfa() {
memset(visit, 0, sizeof visit);
memset(dis, 0x3f, sizeof dis);
queue<int> q;
q.push(s);
dis[s] = 0, visit[s] = 1, flow[s] = INF, pre[t] = -1;
while(!q.empty()) {
int temp = q.front();
q.pop();
visit[temp] = 0;
for(int i = head[temp]; ~i; i = nex[i]) {
if(cap[i] > 0 && dis[to[i]] > dis[temp] + value[i]) {
dis[to[i]] = dis[temp] + value[i];
flow[to[i]] = min(flow[temp], cap[i]);
pre[to[i]] = temp;
id[to[i]] = i;
if(!visit[to[i]]) {
q.push(to[i]);
visit[to[i]] = 1;
}
}
}
}
return pre[t] != -1;
}
int min_cost_and_max_flow() {
int max_flow = 0, min_cost = 0;
while(spfa()) {
max_flow += flow[t];
min_cost += flow[t] * dis[t];
int p = t;
while(p != s) {
cap[id[p]] -= flow[t];
cap[id[p] ^ 1] += flow[t];
p = pre[p];
}
}
printf("%d %d
", max_flow, min_cost);
}
void init() {
memset(head, -1, sizeof head);
cnt = 0;
}
int main() {
// freopen("in.txt", "r", stdin);
init();
scanf("%d %d %d %d", &n, &m, &s, &t);
int x, y, f, w;
for(int i = 0; i < m; i++) {
scanf("%d %d %d %d", &x, &y, &f, &w);
add(x, y, f, w);
add(y, x, 0, -w);
}
min_cost_and_max_flow();
return 0;
}
两个假的Dijkstra
洛谷模板题卡爆DIjkstra。
好像第一个稍优一点。
第一个假的Dijkstra
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N1 = 5e3 + 10;
const int INF = 0x3f3f3f3f;
int dis[N1], h[N1], flow[N1], pre[N1], id[N1], visit[N1], n, m, s, t;
struct Edge {
int to, cap, value, rever;
Edge(int _to, int _cap, int _value, int _rever) : to(_to), cap(_cap), value(_value), rever(_rever) {}
};
vector<Edge> G[N1];
void add(int x, int y, int f, int w) {
Edge temp1 = Edge(y, f, w, G[y].size());
Edge temp2 = Edge(x, 0, -w, G[x].size());
G[x].pb(temp1);
G[y].pb(temp2);
}
int min_cost_and_max_flow() {
int min_cost = 0, max_flow = 0;
memset(dis, 0x3f, sizeof dis);
for(;;) {
priority_queue<PII, vector<PII>, greater<PII> > q;
dis[s] = 0, flow[s] = INF;
q.push(mp(0, s));
while(!q.empty()) {
PII temp = q.top();
q.pop();
if(visit[temp.y]) continue;
visit[temp.y] = 1;
int u = temp.y;
for(int i = 0; i < G[u].size(); i++) {
Edge v = G[u][i];
if(v.cap > 0 && dis[v.to] > dis[u] + v.value + h[u] - h[v.to]) {
dis[v.to] = dis[u] + v.value + h[u] - h[v.to];
flow[v.to] = min(v.cap, flow[u]);
pre[v.to] = u;
id[v.to] = i;
q.push(mp(dis[v.to], v.to));
}
}
}
if(visit[t] == 0) break;
max_flow += flow[t];
for(int i = 1; i <= n; i++) {
h[i] += dis[i];
dis[i] = INF;
visit[i] = 0;
}
min_cost += flow[t] * h[t];
int p = t;
while(p != s) {
G[pre[p]][id[p]].cap -= flow[t];
G[p][ G[pre[p]][id[p]].rever].cap += flow[t];
p = pre[p];
}
}
printf("%d %d
", max_flow, min_cost);
}
int main() {
// freopen("in.txt", "r", stdin);
scanf("%d %d %d %d", &n, &m, &s, &t);
int x, y, f, w;
for(int i = 0; i < m; i++) {
scanf("%d %d %d %d", &x, &y, &f, &w);
add(x, y, f, w);
}
min_cost_and_max_flow();
return 0;
}
第二个假的Dijkstra
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef pair<int, int> PII;
const int N1 = 5e3 + 10, N2 = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int head[N1], to[N2], nex[N2], cap[N2], value[N2], cnt;
int visit[N1], flow[N1], dis[N1], pre[N1], id[N1], h[N1], n, m, s, t;
void init() {
memset(head, -1, sizeof head);
cnt = 0;
}
void add(int x, int y, int f, int w) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
cap[cnt] = f;
head[x] = cnt++;
}
int min_cost_and_max_flow() {
int min_cost = 0, max_flow = 0;
memset(dis, 0x3f, sizeof dis);
for(;;) {
priority_queue<PII, vector<PII>, greater<PII> > q;
q.push(mp(0, s));
flow[s] = INF, dis[s] = 0;
while(!q.empty()) {
int temp = q.top().second;
q.pop();
// if(temp == t) break;
if(visit[temp]) continue;
visit[temp] = 1;
// if(temp == t) break;
for(int i = head[temp]; ~i; i = nex[i]) {
if(cap[i] > 0 && dis[to[i]] > dis[temp] + value[i] + h[temp] - h[to[i]]) {
dis[to[i]] = dis[temp] + value[i] + h[temp] - h[to[i]];
flow[to[i]] = min(flow[temp], cap[i]);
pre[to[i]] = temp;
id[to[i]] = i;
q.push(mp(dis[to[i]], to[i]));
}
}
}
if(visit[t] == 0) break;
for(int i = 1; i < n; i++) {
h[i] += dis[i];
visit[i] = 0;
dis[i] = INF;
}
max_flow += flow[t];
min_cost += flow[t] * h[t];
int p = t;
while(p != s) {
cap[id[p]] -= flow[t];
cap[id[p] ^ 1] += flow[t];
p = pre[p];
}
}
printf("%d %d
", max_flow, min_cost);
}
int main() {
// freopen("in.txt", "r", stdin);
init();
scanf("%d %d %d %d", &n, &m, &s, &t);
int x, y, f, w;
for(int i = 0; i < m; i++) {
scanf("%d %d %d %d", &x, &y, &f, &w);
add(x, y, f, w);
add(y, x, 0, -w);
}
min_cost_and_max_flow();
return 0;
}
以上是关于最小费用最大流 和 最大流模板的主要内容,如果未能解决你的问题,请参考以下文章