最大流
const int MAXN = 10010, MAXM = 20010, INF = 1e9;
struct MaxFlow {
int S, T, head[MAXN], cur[MAXN], dis[MAXN], cnt = 1;
bool vis[MAXN];
struct edge {int v, c, nxt;} e[MAXM * 2];
void add(int u, int v, int c) {
e[++cnt] = {v, c, head[u]}, head[u] = cnt;
e[++cnt] = {u, 0, head[v]}, head[v] = cnt;
}
void rebuild() {
for (int i = 2; i <= cnt; i += 2)
e[i].c += e[i ^ 1].c, e[i ^ 1].c = 0;
}
void clear() {
memset(head, 0, sizeof(head));
cnt = 1;
}
bool bfs() {
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
memcpy(cur, head, sizeof(head));
queue<int> q; q.push(S), vis[S] = 1, dis[S] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; i; i = e[i].nxt) {
if (!e[i].c || vis[e[i].v]) continue;
dis[e[i].v] = dis[u] + 1, vis[e[i].v] = 1;
q.push(e[i].v);
}
}
return vis[T];
}
int dfs(int now, int flow) {
if(now == T) return flow;
int res = 0;
for(int i = cur[now]; i && res < flow; i = e[i].nxt) {
if(!e[i].c || dis[e[i].v] != dis[now] + 1) {
cur[now] = e[i].nxt;
continue;
}
int tmp = dfs(e[i].v, min(flow - res, e[i].c));
e[i].c -= tmp, e[i ^ 1].c += tmp, res += tmp;
if(res < flow) cur[now] = e[i].nxt;
}
return res;
}
int solve() {
int ans = 0;
while (bfs()) ans += dfs(S, INF);
return ans;
}
} G;
MCMF
const int MAXN = 10010, MAXM = 20010, INF = 1e9;
struct MCMF {
int S, T, head[MAXN], cnt = 1;
int dis[MAXN], pre[MAXN], pree[MAXN];
bool in[MAXN];
struct edge {int v, c, w, nxt;} e[MAXM * 2];
void add(int u, int v, int c, int w) {
e[++cnt] = {v, c, w, head[u]}, head[u] = cnt;
e[++cnt] = {u, 0, -w, head[v]}, head[v] = cnt;
}
void rebuild() {
for (int i = 1; i <= cnt; i += 2)
e[i].c += e[i ^ 1].c, e[i ^ 1].c = 0;
}
void clear() {
memset(head, 0, sizeof(head));
cnt = 1;
}
bool SPFA() {
memset(dis, 0x3f, sizeof(dis));
queue<int> q; q.push(S), in[S] = 1, dis[S] = 0;
while (!q.empty()) {
int u = q.front(); q.pop(), in[u] = 0;
for (int i = head[u]; i; i = e[i].nxt) {
if (!e[i].c || dis[e[i].v] <= dis[u] + e[i].w) continue;
dis[e[i].v] = dis[u] + e[i].w;
pre[e[i].v] = u, pree[e[i].v] = i;
if (!in[e[i].v]) in[e[i].v] = 1, q.push(e[i].v);
}
}
return dis[T] <= INF;
}
pair<int, int> getpath() {
int now = T, flow = INF, cost = 0;
while (now != S) flow = min(flow, e[pree[now]].c), now = pre[now];
now = T;
while (now != S) {
int tmp = pree[now]; now = pre[now];
e[tmp].c -= flow, e[tmp ^ 1].c += flow;
cost += flow * e[tmp].w;
}
return {flow, cost};
}
pair<int, int> solve() {
pair<int, int> ans(0, 0);
while (SPFA()) {
auto tmp = getpath();
ans.first += tmp.first, ans.second += tmp.second;
}
return ans;
}
} G;
SAM
const int MAXN = 50010;
struct SAM {
struct node {
int nxt[26], fa, len;
} t[MAXN];
int cnt, lst, sz[MAXN], ind[MAXN];
int dfn[MAXN], dep[MAXN], tot;
int lg[MAXN], tr[20][MAXN];
SAM() : cnt(1), lst(1), tot(0) {}
void insert(int x) {
int cur = ++cnt, p = lst;
t[cur].len = t[lst].len + 1;
for (; p && t[p].nxt[x] == 0; p = t[p].fa)
t[p].nxt[x] = cur;
int q = t[p].nxt[x];
if (q == 0) t[cur].fa = 1;
else if (t[q].len == t[p].len + 1) t[cur].fa = q;
else {
int r = ++cnt;
t[r] = t[q], t[r].len = t[p].len + 1;
for (; p && t[p].nxt[x] == q; p = t[p].fa)
t[p].nxt[x] = r;
t[q].fa = t[cur].fa = r;
}
sz[cur] = 1, lst = cur;
}
vector<int> e[MAXN];
void dfs(int now, int ndep) {
tr[0][dfn[now] = ++tot] = now, dep[now] = ndep;
for (int v : e[now])
dfs(v, ndep + 1), sz[now] += sz[v];
}
void build(string s) {
lg[1] = 0;
for (int i = 2; i < MAXN; i++)
lg[i] = lg[i / 2] + 1;
for (int i = 0; i < s.size(); i++)
insert(s[i] - 'a'), ind[i] = lst;
for (int i = 2; i <= cnt; i++)
e[t[i].fa].push_back(i);
dfs(1, 0);
for (int i = 1; i <= lg[MAXN - 1]; i++) {
int x = 1 << i;
for (int j = 1; j + x - 1 <= tot; j++) {
if (dep[tr[i - 1][j]] < dep[tr[i - 1][j + x / 2]])
tr[i][j] = tr[i - 1][j];
else tr[i][j] = tr[i - 1][j + x / 2];
}
}
}
int LCA(int x, int y) {
if (x == y) return x;
x = dfn[x], y = dfn[y];
if (x > y) swap(x, y);
int len = lg[y - (x++)];
if (dep[tr[len][x]] < dep[tr[len][y - (1 << len) + 1]])
return t[tr[len][x]].fa;
return t[tr[len][y - (1 << len) + 1]].fa;
}
int LCS(int x, int y) {
return t[LCA(ind[x], ind[y])].len;
}
void clear() {
do {
memset(t[cnt].nxt, 0, sizeof(t[cnt].nxt));
t[cnt].fa = t[cnt].len = 0;
} while (--cnt);
cnt = lst = 1, tot = 0;
}
} T;