题目
最小割树模板
算法详解及证明见:
2016年国家队候选队员论文
《浅谈无向图最小割问题的一些算法及应用——绍兴一中 王文涛》
3.2节
CODE
#include <bits/stdc++.h>
using namespace std;
template<class T>inline void read(T &x) {
char ch; while(!isdigit(ch=getchar()));
for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
}
const int MAXN = 855;
const int MAXM = 8505;
const int inf = 1e9;
int n, m, Q;
int info[MAXN], fir[MAXN], to[MAXM<<1], nxt[MAXM<<1], c[MAXM<<1], C[MAXM<<1], cnt;
inline void link(int u, int v, int cc, int rc) {
to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; C[cnt] = cc;
to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt; C[cnt] = rc;
}
int dis[MAXN];
queue<int>q;
int S, T;
bool bfs() {
memset(dis, -1, sizeof dis);
dis[S] = 0; q.push(S);
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = fir[u], v; i; i = nxt[i])
if(c[i] && !(~dis[v=to[i]]))
dis[v] = dis[u] + 1, q.push(v);
}
return ~dis[T];
}
bool vis[MAXN];
int aug(int u, int Max) {
if(u == T) return Max;
int delta, flow = 0;
vis[u] = 1;
for(int v, &i = info[u]; i; i = nxt[i])
if(c[i] && !vis[v=to[i]] && dis[v] == dis[u]+1 && (delta=aug(v, min(Max-flow, c[i])))) {
c[i] -= delta; c[i^1] += delta; flow += delta;
if(flow == Max) break;
}
vis[u] = 0;
return flow;
}
int maxflow(int ss, int tt) {
S = ss, T = tt;
int re = 0;
while(bfs()) memcpy(info, fir, sizeof info), re += aug(S, inf);
return re;
}
int fa[MAXN], val[MAXN], ans[MAXN][MAXN], seq[MAXN*MAXN], cur;
void dfs(int u) {
if(vis[u]) return;
vis[u] = 1;
for(int i = fir[u]; i; i = nxt[i])
if(c[i]) dfs(to[i]);
}
vector<pair<int,int> >e[MAXN];
void getans(int u, int ff, int now, int s) {
ans[s][u] = now;
for(int i = e[u].size()-1, v; i >= 0; --i)
if((v=e[u][i].first) != ff)
getans(v, u, min(now, e[u][i].second), s);
}
int main () {
read(n), read(m); cnt = 1;
for(int i = 1, u, v, c; i <= m; ++i) {
read(u), read(v), read(c);
link(u, v, c, c);
}
fa[1] = 0;
for(int i = 2; i <= n; ++i) fa[i] = 1;
for(int i = 2; i <= n; ++i) {
memcpy(c, C, sizeof c);
val[i] = maxflow(i, fa[i]);
dfs(i);
for(int j = i+1; j <= n; ++j)
if(vis[j] && fa[i] == fa[j]) fa[j] = i;
memset(vis, 0, sizeof vis);
}
for(int i = 2; i <= n; ++i)
e[fa[i]].push_back(make_pair(i, val[i])),
e[i].push_back(make_pair(fa[i], val[i]));
cur = 0;
for(int i = 1; i <= n; ++i) {
getans(i, 0, inf, i);
for(int j = i+1; j <= n; ++j)
seq[++cur] = ans[i][j];
}
sort(seq + 1, seq + cur + 1);
cur = unique(seq + 1, seq + cur + 1) - seq - 1;
printf("%d
", cur);
}