【网络流】

ISAP 最大流 赛事首选
无向图将反向边权值改为v即可。

#include<bits/stdc++.h>

using namespace std;

const int oo = 0x7f7f7f7f;
const int N = 10010;
const int M = 100010;

template <typename T>
T read(){
    T n(0), f(1);
    char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for(; isdigit(ch); ch = getchar()) n = n*10 + ch-48;
    return n*f;
}
#define read() read<int>()

int n, m, e, S, T;
int to[M<<1], nxt[M<<1], w[M<<1];
int Begin[N], h[N], gap[N];

void addedge(int x, int y, int v){
    to[e] = y; nxt[e] = Begin[x]; w[e] = v; Begin[x] = e++;
    to[e] = x; nxt[e] = Begin[y]; w[e] = 0; Begin[y] = e++;
}

int dfs(int u, int cost){
    if(u == T) return cost;
    int minh = n-1, lv = cost, d;
    for(int i = Begin[u]; i != -1; i = nxt[i]){
        int v = to[i], val = w[i];
        if(val > 0){
            if(h[v] + 1 == h[u]){
                d = min(lv, val);
                d = dfs(v, d);
                w[i] -= d;
                w[i^1] += d;
                lv -= d;
                if(h[S] >= n) return cost-lv;
                if(!lv) break;
            }
            minh = min(minh, h[v]);
        }
    }
    if(lv == cost){
        --gap[h[u]];
        if(!gap[h[u]]) h[S] = n;
        h[u] = minh+1;
        ++gap[h[u]];
    }
    return cost-lv;
}

int sap(int s, int t){
    S = s; T = t;
    memset(gap, 0, sizeof(gap));
    memset(h, 0, sizeof(h));
    gap[s] = n;
    int ret = 0;
    while(h[s] < n){
        ret += dfs(s, oo);
    }
    return ret;
}

int main(){
    memset(Begin, -1, sizeof(Begin));
    int s, t;
    n = read(); m = read();
    s = read(); t = read();
    for(int i = 1; i <= m; ++i){
        int x, y, v;
        x = read(); y = read(); v = read();
        addedge(x, y, v);
    }

    printf("%d
", sap(s, t));
    return 0;
}

增广路算法求最大流
模板LG P3376
DFS太慢,EK算法其实也很慢....(既然是NOIP选手不掌握fastest也没问题吧)

#include<bits/stdc++.h>

using namespace std;

const int oo = 0x7f7f7f7f;
const int N = 10010;

template <typename T>
T read(){
	T n(0), f(1);
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) n = n*10 + ch-48;
	return n*f;
}

struct Edge{
	int u, v, cap, flow;
	Edge(int from, int to, int c, int f):u(from), v(to), cap(c), flow(f){}
};

int n, m;
int a[N], p[N];
vector<Edge> edges;
vector<int> G[N];

#define pb push_back

void init(){
	for(int i = 1; i <= n; ++i) G[i].clear();
	edges.clear();
}

void addedge(int u, int v, int cap){
	edges.pb(Edge(u, v, cap, 0));
	edges.pb(Edge(v, u, 0, 0));
	int tm = edges.size();
	G[u].pb(tm-2);
	G[v].pb(tm-1);
}

int EK(int s, int t){
	int flow = 0;
	for(;;){
		memset(a, 0, sizeof(a));
		queue<int> Q;
		Q.push(s);
		a[s] = oo;
		while(!Q.empty()){
			int x = Q.front(); Q.pop();
			for(int i = 0; i < G[x].size(); ++i){
				Edge& e = edges[G[x][i]];
				if(!a[e.v] && e.cap > e.flow){
					p[e.v] = G[x][i];
					a[e.v] = min(a[x], e.cap-e.flow);
					Q.push(e.v);
				}
			}
			if(a[t]) break;
		}
		if(!a[t]) break;
		for(int i = t; i != s; i = edges[p[i]].u){
			edges[p[i]].flow += a[t];
			edges[p[i]^1].flow -= a[t];
		}
		flow += a[t];
	}
	return flow;
}

int main(){
	int s, t;
	n = read<int>(); m = read<int>();
	s = read<int>(); t = read<int>();

	init();
	
	for(int i = 1; i <= m; ++i){
		int u, v, w;
		u = read<int>();
		v = read<int>();
		w = read<int>();
		addedge(u, v, w);
	}
	
	printf("%d
", EK(s, t));
	
	return 0;
}

最小费用最大流
模板LG P3381
用Bellmanford求

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 5010;
const int M = 50010;
const int oo = 0x7f7f7f7f;

template <typename T>
T read(){
	T n(0), f(1);
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) n = n*10 + ch-48;
	return n*f;
}

#define read() read<int>()

struct Edge{
	int from, to, cap, flow, cost;
	Edge(int u, int v, int c, int f, int val):from(u), to(v), cap(c), flow(f), cost(val){}
};

int n, m;
vector<Edge> edges;
vector<int> G[N];
int a[N], d[N], p[N], inq[N];

#define pb push_back

void addedge(int x, int y, int w, int v){
	edges.pb(Edge(x, y, w, 0, v));
	edges.pb(Edge(y, x, 0, 0, -v));
	int tm = edges.size();
	G[x].pb(tm-2);
	G[y].pb(tm-1);
}

void init(){
	for(int i = 1; i <= n; ++i) G[i].clear();
	edges.clear();
}

bool BMFD(int s, int t, int& flow, ll& cost){
	memset(inq, 0, sizeof(inq));
	for(int i = 1; i <= n; ++i) d[i] = oo;
	d[s] = p[s] = 0; a[s] = oo; inq[s] = 1;

	queue<int> Q;
	Q.push(s);
	while(!Q.empty()){
		int u = Q.front(); Q.pop();
		inq[u] = 0;
		for(int i = 0; i < G[u].size(); ++i){
			Edge& e = edges[G[u][i]];
			if(e.cap > e.flow && d[e.to] > d[u]+e.cost){
				d[e.to] = d[u] + e.cost;
				a[e.to] = min(a[u], e.cap-e.flow);
				p[e.to] = G[u][i];
				if(!inq[e.to]){ Q.push(e.to); inq[e.to] = 1; }
			}
		}
	}
	if(d[t] == oo) return false;
	flow += a[t];
	cost += 1ll*d[t]*a[t];
	for(int i = t; i != s; i = edges[p[i]].from){
		edges[p[i]].flow += a[t];
		edges[p[i]^1].flow -= a[t];
	}
	return true;
}

int MCMF(int s, int t, ll& cost){
	int flow = 0; cost = 0;
	while(BMFD(s, t, flow, cost));
	return flow;
}

int main(){
	int s, t;

	n = read(); m = read();
	s = read(); t = read();
	init();
	
	for(int i = 1; i <= m; ++i){
		int x, y, w, v;
		x = read(); y = read();
		w = read(); v = read();
		addedge(x, y, w, v);
	}

	ll cost = 0;
	printf("%d ", MCMF(s, t, cost));
	printf("%lld
", cost);
	return 0;
}
原文地址:https://www.cnblogs.com/hanser/p/7816283.html