Bellman-Ford 朴素做法
struct edge {
int from, to, cap, flow;
edge (int _from, int _to, int _cap, int _flow):from(_from), to(_to), cap(_cap), flow(_flow){}
};
struct EdmondsKarp {
int n, m;
vector <edge> edges; // 边数的两倍
vector <int> g[maxn]; // g[i][j] 表示节点 i 的第 j 条边在 e 数组中的位置
int a[maxn]; // 当起点到 i 的可改进量
int p[maxn]; // 最短路树上 p 的入弧编号
void init(int n)
{
for(int i = 0;i <= n;i ++)
g[i].clear();
edges.clear();
}
void addEdge(int from, int to, int cap)
{
edges.push_back(edge(from, to, cap, 0));
edges.push_back(edge(to, from, 0, 0));
m = edges.size();
g[from].push_back(m - 2); // 将每一条边的编号存下来
g[to].push_back(m - 1); // m - 1 肯定是奇数 不难发现: (m - 1) ^ 1 = (m - 2)
} // (m - 2) ^ 1 = (m - 1)
int maxflow(int s, int t)
{
int flow = 0;
while(1)
{
queue <int> q;
q.push(s);
memset(a, 0, sizeof(a));
a[s] = INF;
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.to] && e.cap > e.flow)
{
p[e.to] = g[x][i]; // 存下路径
a[e.to] = min(a[x], e.cap - e.flow); // emmm...从起点到终点选出最小的可通过流量
q.push(e.to);
}
}
if(a[t]) break; // 当到达终点时 a[t] 必然不为 0 ,由此可推出
}
if(!a[t]) break; // 当 a[t] 为 0 ,则说明没有到达,不存在解
for(int u = t;u != s;u = edges[p[u]].from) // 按路径回溯,修改流量
{
edges[p[u]].flow += a[t];
edges[p[u] ^ 1].flow -= a[t]; // 原因同上
}
flow += a[t];
}
return flow;
}
}EK;