终于找到了心仪的网络流模版
首先是Dinic
/*
Dinic 模版 (刘汝佳) 支持重边 加入当前弧优化
递归写法 如果递归爆栈 改用ISAP
*/
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 1100;
#define INF 0xfffffff
#define met(a, b) memset(a, b, sizeof(a))
struct edge{int from, to, cap, flow;};
int n, m; //结点 边数
vector <edge> edges; //边表
vector <int> G[N]; //邻接表 G[i][j] 结点i的第j条边在e数组中的序号
bool vis[N]; // bfs使用
int d[N]; // 从起点到i的距离
int cur[N]; //当前弧下标
void addedge (int from, int to, int cap)
{
edges.push_back((edge){from, to, cap, 0});
edges.push_back((edge){to, from, 0, 0});
int tm = edges.size();
G[from].push_back(tm-2);
G[to].push_back(tm-1);
}
bool bfs (int s, int t)
{
met (vis, false);
queue <int> que;
que.push (s);
d[s] = 0;
vis[s] = true;
while (que.size())
{
int x = que.front(); que.pop();
for (int i=0; i<G[x].size(); i++)
{
edge &e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = true;
d[e.to] = d[x] + 1;
que.push(e.to);
}
}
}
return vis[t];
}
int dfs (int x, int t, int a)
{
if (x == t || a == 0) return a;
int flow = 0, f;
for (int &i=cur[x]; i<G[x].size(); i++)
{
edge &e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] && (f = dfs(e.to, t, min(a, e.cap - e.flow))) > 0)
{
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
int maxflow (int s, int t)
{
int flow = 0;
while (bfs(s, t))
{
met (cur, 0);
flow += dfs(s, t, INF);
}
return flow;
}
ISAP
//IASP (刘汝佳)
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 1100;
const int INF = 0xfffffff;
#define met(a, b) memset(a, b, sizeof(a))
struct edge{int from, to, cap, flow;};
int n, m; //结点 边数
vector <edge> edges; //边表
vector <int> G[N]; //邻接表 G[i][j] 结点i的第j条边在e数组中的序号
bool vis[N]; // bfs使用
int d[N]; // 从起点到i的距离
int cur[N]; //当前弧下标
int p[N]; //可增广路上的一条弧
int num[N]; //距离标号计数
void addedge (int from, int to, int cap)
{
edges.push_back((edge){from, to, cap, 0});
edges.push_back((edge){to, from, 0, 0});
int tm = edges.size();
G[from].push_back(tm-2);
G[to].push_back(tm-1);
}
int augment (int s, int t)
{
int x = t, a = INF;
while (x != s)
{
edge &e = edges[p[x]];
a = min (a, e.cap - e.flow);
x = edges[p[x]].from;
}
x = t;
while (x != s)
{
edges[p[x]].flow += a;
edges[p[x]^1].flow -= a;
x = edges[p[x]].from;
}
return a;
}
void bfs(int t) //待验证 自己补写的
{
met (vis, false);
queue <int> que;
que.push (t);
d[t] = 0;
vis[t] = true;
while (que.size())
{
int x = que.front();
que.pop();
for (int i=0; i<G[x].size(); i++)
{
edge &e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = true;
d[e.to] = d[x] + 1;
que.push (e.to);
}
}
}
}
int ISAP (int s, int t)
{
int flow = 0;
bfs (t);
// met (num, 0); met (d, 0); // 或者bfs
/*初始标号可以统一设置为0 或者用bfs
单次运行时效率相差不大 多次求解小规模网络流
速度会有明显提升*/
for (int i=0; i<n; i++) num[d[i]]++;
int x = s;
met (cur, 0);
while (d[s] < n)
{
if (x == t)
{
flow += augment(s, t);
x = s;
}
bool ok = false;
for (int i=cur[x]; i<G[x].size(); i++)
{
edge &e = edges[G[x][i]];
if (e.cap > e.flow && d[x] == d[e.to] + 1)
{
ok = true;
p[e.to] = G[x][i];
cur[x] = i;
x = e.to;
break;
}
}
if (!ok)
{
int m = n - 1;
for (int i=0; i<G[x].size(); i++)
{
edge &e = edges[G[x][i]];
if (e.cap > e.flow)
m = min (m, d[e.to]);
}
if (--num[d[x]] == 0)
break; //gap优化
num[d[x] = m + 1]++;
cur[x] = 0;
if (x != s) x = edges[p[x]].from;
}
}
return flow;
}
//最小费用最大流
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 1100;
const int INF = 0xfffffff;
#define met(a, b) memset(a, b, sizeof(a))
struct edge
{
int from, to, cap, flow, cost;
};
int n, m; //结点 边数
vector <edge> edges; //边表
vector <int> G[N]; //邻接表 G[i][j] 结点i的第j条边在e数组中的序号
int inq[N]; //是否在队列中
int d[N]; //bellman-ford 距离
int p[N]; //上一条弧
int a[N]; //可改进量
void init ()
{
for (int i=0; i<n; i++)
G[i].clear();
edges.clear();
}
void addedge (int from, int to, int cap, int cost)
{
edges.push_back((edge)
{
from, to, cap, 0, cost
});
edges.push_back((edge)
{
to, from, 0, 0, -cost
});
int tm = edges.size();
G[from].push_back(tm-2);
G[to].push_back(tm-1);
}
bool bellmanFord (int s, int t, int &flow, int &cost)
{
/*for (int i=0; i<n; i++)
d[i] = INF;*/
fill (d, d + n, INF);
met (inq, 0);
d[s] = 0;
inq[s] = 1;
p[s] = 0;
a[s] = INF;
queue <int> que;
que.push (s);
while (que.size())
{
int u = que.front();
que.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;
p[e.to] = G[u][i];
a[e.to] = min (a[u], e.cap - e.flow);
if (!inq[e.to])
{
que.push (e.to);
inq[e.to] = 1;
}
}
}
}
if (d[t] == INF) return false;
flow += a[t];
cost += d[t] * a[t];
int u = t;
while (u != s)
{
edges[p[u]].flow += a[t];
edges[p[u]^1].flow -= a[t];
u = edges[p[u]].from;
}
return true;
}
int Mincost (int s, int t)
{
int flow = 0, cost = 0;
while (bellmanFord(s, t, flow, cost));
return cost;
}