HLPP
最大流
O(V^3)
| INIT: network g; g.build(nv, ne);
| CALL: res = g.maxflow(s, t);
|
注意
:
不要加入指向源点的边
,
可能死循环
.
\*==================================================*/
#define
typef
int
// type of flow
const
typef inf = 0x3f3f3f3f;
// max of flow
typef minf(typef a, typef b) {
return
a < b ? a : b; }
struct
edge {
int
u, v; typef cuv, cvu, flow;
edge (
int
x=0,
int
y=0, typef cu=0,
typef cv=0, typef f=0)
: u(x), v(y), cuv(cu), cvu(cv), flow(f) {}
int
other(
int
p) {
return
p == u ? v : u; }
typef cap(
int
p) {
return
p == u ? cuv-flow : cvu+flow;
}
void
addflow(
int
p, typef f) { flow += (p == u ? f : -f); }
};
struct
vlist {
int
lv, next[N], idx[2 * N], v;
void
clear(
int
cv) {
v = cv; lv = -1;
memset(idx, -1,
sizeof
(idx));
}
void
insert(
int
n,
int
h) {
next[n] = idx[h]; idx[h] = n;
if
(lv < h) lv = h;
}
int
remove() {
int
r = idx[lv]; idx[lv] = next[idx[lv]];
while
(lv >= 0 && idx[lv] == -1) lv--;
return
r;
}
bool
empty() {
return
lv < 0; }
};
struct
network {
vector<edge> eg;
vector<edge*> net[N];
vlist list;
typef e[N];
int
v, s, t, h[N], hn[2 * N], cur[N];
void
push(
int
);
void
relabel(
int
);
void
build(
int
,
int
);
typef maxflow(
int
,
int
);
};
void
network::push(
int
u) {
edge* te = net[u][cur[u]];
typef ex = minf(te->cap(u), e[u]);
int
p = te->other(u);
if
(e[p] == 0 && p != t) list.insert(p, h[p]);
te->addflow(u, ex); e[u] -= ex; e[p] += ex;
}
void
network::relabel(
int
u) {
int
i, p, mh = 2 * v, oh = h[u];
for
(i = net[u].size()-1; i >= 0; i--) {
p = net[u][i]->other(u);
if
(net[u][i]->cap(u) != 0 && mh > h[p] + 1)
mh = h[p] + 1;
}
hn[h[u]]--; hn[mh]++; h[u] = mh;
cur[u] = net[u].size()-1;
if
(hn[oh] != 0 || oh >= v + 1)
return
;
for
(i = 0; i < v; i++)
if
(h[i] > oh && h[i] <= v && i != s) {
hn[h[i]]--; hn[v+1]++; h[i] = v + 1;
}
}
typef network::maxflow(
int
ss,
int
tt) {
s = ss; t = tt;
int
i, p, u; typef ec;
for
(i = 0; i < v; i++) net[i].clear();
for
(i = eg.size()-1; i >= 0; i--) {
net[eg[i].u].push_back(&eg[i]);
net[eg[i].v].push_back(&eg[i]);
}
memset(h, 0,
sizeof
(h)); memset(hn, 0,
sizeof
(hn));
memset(e, 0,
sizeof
(e)); e[s] = inf;
for
(i = 0; i < v; i++) h[i] = v;
queue<
int
> q; q.push(t); h[t] = 0;
while
(!q.empty()) {
p = q.front(); q.pop();
for
(i = net[p].size()-1; i >= 0; i--) {
u = net[p][i]->other(p);
ec = net[p][i]->cap(u);
if
(ec != 0 && h[u] == v && u != s) {
h[u] = h[p] + 1; q.push(u);
}
}
}
for
(i = 0; i < v; i++) hn[h[i]]++;
for
(i = 0; i < v; i++) cur[i] = net[i].size()-1;
list.clear(v);
for
(; cur[s] >= 0; cur[s]--) push(s);
while
(!list.empty()) {
for
(u = list.remove(); e[u] > 0; ) {
if
(cur[u] < 0) relabel(u);
else if
(net[u][cur[u]]->cap(u) > 0 &&
h[u] == h[net[u][cur[u]]->other(u)]+1)
push(u);
else
cur[u]--;
}
}
return
e[t];
}
void
network::build(
int
n,
int
m) {
v = n; eg.clear();
int
a, b, i; typef l;
for
(i = 0; i < m; i++) {
cin >> a >> b >> l;
eg.push_back(edge(a, b, l, 0));
// vertex: 0 ~ n-1
}
}