LCT
struct LinkCutTree {
struct Node {
int ch[2];
int fa;
int rev_tag;
// ...
};
vector<Node> tree;
map<pair<int, int>, bool> edge;
void init(int n /* ... */) {
tree.resize(n + 10);
for (int i = 1; i <= n; ++i) {
tree[i].ch[0] = tree[i].ch[1] = tree[i].fa = tree[i].rev_tag = 0;
// ...
}
}
void pushUp(int x) {
// ...
}
void pushDown(int x) {
if (tree[x].rev_tag) {
swap(tree[tree[x].ch[0]].ch[0], tree[tree[x].ch[0]].ch[1]);
tree[tree[x].ch[0]].rev_tag ^= 1;
swap(tree[tree[x].ch[1]].ch[0], tree[tree[x].ch[1]].ch[1]);
tree[tree[x].ch[1]].rev_tag ^= 1;
tree[x].rev_tag = 0;
}
// ...
}
int get(int x) { return tree[tree[x].fa].ch[1] == x; }
int isRoot(int x) { return tree[tree[x].fa].ch[0] != x && tree[tree[x].fa].ch[1] != x; }
void rotate(int x) {
int y = tree[x].fa, z = tree[y].fa, t = get(x);
if (!isRoot(y)) tree[z].ch[get(y)] = x;
tree[y].ch[t] = tree[x].ch[t ^ 1], tree[tree[x].ch[t ^ 1]].fa = y;
tree[x].ch[t ^ 1] = y, tree[y].fa = x;
tree[x].fa = z;
pushUp(y);
}
void update(int x) {
if (!isRoot(x)) update(tree[x].fa);
pushDown(x);
}
void splay(int x) {
update(x);
for (int fa = tree[x].fa; !isRoot(x); rotate(x), fa = tree[x].fa) {
if (!isRoot(fa)) rotate(get(fa) == get(x) ? fa : x);
}
pushUp(x);
}
int access(int x) {
splay(x);
tree[x].ch[1] = 0, pushUp(x);
while (tree[x].fa) {
int fa = tree[x].fa;
splay(fa), tree[fa].ch[1] = x, pushUp(fa);
x = fa;
}
return x;
}
void makeRoot(int x) {
access(x), splay(x);
swap(tree[x].ch[0], tree[x].ch[1]);
tree[x].rev_tag ^= 1;
}
int findRoot(int x) {
x = access(x);
pushDown(x);
while (tree[x].ch[0]) x = tree[x].ch[0], pushDown(x);
splay(x);
return x;
}
void link(int x, int y) {
if (findRoot(x) == findRoot(y)) return;
makeRoot(x), tree[x].fa = y;
edge[make_pair(x, y)] = edge[make_pair(y, x)] = 1;
}
void cut(int x, int y) {
if (!edge[make_pair(x, y)]) return;
makeRoot(x), access(x), splay(y), tree[y].fa = 0;
edge[make_pair(x, y)] = edge[make_pair(y, x)] = 0;
}
int split(int x, int y) {
makeRoot(x);
return access(y);
}
// ...
} LCT;
SA
int n;
string s;
vector<int> sa, rk, height;
vector<int> cntSort_cnt, cntSort_rk;
void cntSort(vector<int> val, vector<int> &res) {
fill(cntSort_cnt.begin(), cntSort_cnt.end(), 0);
for (int i = 1; i <= n; ++i) ++cntSort_cnt[val[i]];
for (int i = 1; i < cntSort_cnt.size(); ++i) cntSort_cnt[i] += cntSort_cnt[i - 1];
for (int i = n; i >= 1; --i) {
cntSort_rk[res[i]] = cntSort_cnt[val[res[i]]]--;
}
for (int i = 1; i <= n; ++i) res[cntSort_rk[i]] = i;
}
void initSA() {
sa.resize(n + 10), rk.resize(n + 10), height.resize(n + 10);
cntSort_cnt.resize(max(n + 10, 150));
cntSort_rk.resize(n + 10);
for (int i = 1; i <= n; ++i) {
sa[i] = i;
rk[i] = (int)s[i];
}
cntSort(rk, sa);
int cnt = 0;
for (int i = 1; i <= n; ++i) {
if (s[sa[i]] != s[sa[i - 1]]) ++cnt;
rk[sa[i]] = cnt;
}
vector<int> tmp1(n + 10), tmp2(n + 10);
for (int l = 1; l < n; l <<= 1) {
bool flg = 0;
for (int i = 2; i <= n; ++i) {
if (rk[sa[i]] == rk[sa[i - 1]]) flg = 1;
}
if (!flg) break;
for (int i = 1; i <= n; ++i) {
if (i + l > n) tmp2[i] = 0;
else tmp2[i] = rk[i + l];
}
cntSort(tmp2, sa);
for (int i = 1; i <= n; ++i) tmp1[i] = rk[i];
cntSort(tmp1, sa);
int cnt = 0;
for (int i = 1; i <= n; ++i) {
if (tmp1[sa[i]] != tmp1[sa[i - 1]] || tmp2[sa[i]] != tmp2[sa[i - 1]]) ++cnt;
rk[sa[i]] = cnt;
}
}
cnt = 0;
for (int i = 1; i <= n; ++i) {
if (rk[i] == 1) continue;
if (cnt) --cnt;
while (i + cnt <= n && sa[rk[i] - 1] + cnt <= n && s[i + cnt] == s[sa[rk[i] - 1] + cnt]) ++cnt;
height[rk[i]] = cnt;
}
}
SAM
string s;
struct Node {
int len;
int fa;
array<int, 26> son;
int cnt;
Node(int _len = 0, int _fa = 0, int _cnt = 0) {
len = _len, fa = _fa, cnt = _cnt;
for (int i = 0; i < 26; ++i) son[i] = 0;
}
};
vector<Node> SAM;
void initSAM() {
SAM.emplace_back();
SAM.emplace_back(); // root
}
int extendSAM(int last, int ch) {
SAM.emplace_back(SAM[last].len + 1, 0, 1);
int now = SAM.size() - 1;
for (; last && !SAM[last].son[ch]; last = SAM[last].fa) SAM[last].son[ch] = now;
if (!last) SAM[now].fa = 1;
else {
if (SAM[SAM[last].son[ch]].len == SAM[last].len + 1) SAM[now].fa = SAM[last].son[ch];
else {
int tmp = SAM[last].son[ch];
SAM.emplace_back(SAM[last].len + 1, SAM[tmp].fa);
int new_node = SAM.size() - 1;
SAM[new_node].son = SAM[tmp].son;
SAM[tmp].fa = SAM[now].fa = new_node;
for (; SAM[last].son[ch] == tmp; last = SAM[last].fa) SAM[last].son[ch] = new_node;
}
}
return now;
}
vector<vector<int> > T;
void dfs(int x) {
for (int i = 0; i < T[x].size(); ++i) {
int y = T[x][i];
dfs(y);
SAM[x].cnt += SAM[y].cnt;
}
}
void buildSAM() {
initSAM();
for (int i = 0, cur = 1; i < s.size(); ++i) {
cur = extendSAM(cur, s[i] - 'a');
}
T.resize(SAM.size());
for (int i = 2; i < SAM.size(); ++i) T[SAM[i].fa].emplace_back(i);
dfs(1);
}
最大流
namespace MaxFlow {
// 你需要做的:给 n,s,t 赋值,用 addEdge 加边,然后调用 dinic 函数获得这个网络的最大流
const int kMaxN = 10005;
const int kMaxM = 100005;
const long long kInf = 1e15;
int n, s, t;
struct Edge {
int u, v, nxt;
long long w;
} e[kMaxM];
int head[kMaxN], tot = 1;
void addEdge(int u, int v, long long w) {
e[++tot].u = u, e[tot].v = v, e[tot].w = w;
e[tot].nxt = head[u], head[u] = tot;
e[++tot].u = v, e[tot].v = u, e[tot].w = 0;
e[tot].nxt = head[v], head[v] = tot;
}
long long dis[kMaxN];
bool vis[kMaxN];
bool bfs() {
queue<int> que;
fill(dis + 1, dis + n + 1, kInf), fill(vis + 1, vis + n + 1, 0);
que.emplace(s); dis[s] = 0, vis[s] = 1;
while (!que.empty()) {
int x = que.front(); que.pop();
for (int i = head[x]; i; i = e[i].nxt) {
if (vis[e[i].v] || !e[i].w) continue;
vis[e[i].v] = 1;
dis[e[i].v] = dis[x] + 1;
que.emplace(e[i].v);
}
}
return dis[t] < kInf;
}
int cur[kMaxN];
long long dfs(int now, long long flow) {
if (now == t) return flow;
long long rest = flow;
for (int &i = cur[now]; i; i = e[i].nxt) {
if (!e[i].w || dis[now] + 1 != dis[e[i].v]) continue;
long long t = dfs(e[i].v, min(e[i].w, rest));
e[i].w -= t, e[i ^ 1].w += t;
rest -= t;
if (!rest) break;
}
return flow - rest;
}
long long dinic() {
long long ans = 0;
while (bfs()) {
for (int i = 1; i <= n; ++i) cur[i] = head[i];
ans += dfs(s, kInf);
}
return ans;
}
}
最小费用最大流
namespace MinCostMaxFlow {
const int kMaxN = 1e5 + 10;
const int kMaxM = 1e6 + 10;
const long long kInf = 1e15;
int n, s, t;
struct Edge {
int u, v;
long long w, c;
int nxt;
} e[kMaxM << 1];
int head[kMaxN], tot = 1;
void addEdge(int u, int v, long long w, long long c) {
e[++tot].u = u, e[tot].v = v, e[tot].w = w, e[tot].c = c;
e[tot].nxt = head[u], head[u] = tot;
e[++tot].u = v, e[tot].v = u, e[tot].w = 0, e[tot].c = -c;
e[tot].nxt = head[v], head[v] = tot;
}
long long dis[kMaxN];
int in_edge[kMaxN];
queue<int> que;
bool vis[kMaxN];
bool spfa() {
fill(dis + 1, dis + n + 1, kInf);
dis[s] = 0, que.emplace(s), vis[s] = 0;
while (!que.empty()) {
int x = que.front(); que.pop();
vis[x] = 0;
for (int i = head[x]; i; i = e[i].nxt) {
if (!e[i].w) continue;
int y = e[i].v;
if (dis[x] + e[i].c < dis[y]) {
dis[y] = dis[x] + e[i].c;
in_edge[y] = i;
if (!vis[y]) {
vis[y] = 1;
que.emplace(y);
}
}
}
}
return dis[t] != kInf;
}
pair<long long, long long> solve() {
long long max_flow = 0, min_cost = 0;
while (spfa()) {
int cur = t;
long long flow = kInf, cost = 0;
while (cur != s) {
flow = min(flow, e[in_edge[cur]].w);
cost += e[in_edge[cur]].c;
cur = e[in_edge[cur]].u;
}
max_flow += flow, min_cost += flow * cost;
cur = t;
while (cur != s) {
e[in_edge[cur]].w -= flow;
e[in_edge[cur] ^ 1].w += flow;
cur = e[in_edge[cur]].u;
}
}
return make_pair(max_flow, min_cost);
}
}
圆方树
vector<int> G[kMaxN];
vector<int> T[kMaxN << 1];
namespace BuildCSTree {
int tot;
int dfn[kMaxN], tim, low[kMaxN];
bool vis[kMaxN];
void dfs1(int x) {
dfn[x] = low[x] = ++tim;
vis[x] = 1;
for (int y : G[x]) {
if (!vis[y]) {
dfs1(y);
low[x] = min(low[x], low[y]);
}
else low[x] = min(low[x], dfn[y]);
}
}
void dfs2(int x, int bcc_id) {
T[bcc_id].emplace_back(x), T[x].emplace_back(bcc_id);
vis[x] = 1;
for (int y : G[x]) {
if (vis[y]) continue;
if (low[y] < dfn[x]) dfs2(y, bcc_id);
else {
++tot;
T[x].emplace_back(tot), T[tot].emplace_back(x);
dfs2(y, tot);
}
}
}
void build() {
for (int i = 1; i <= n; ++i) {
if (!vis[i]) dfs1(i);
}
fill(vis + 1, vis + n + 1, 0);
tot = n;
for (int i = 1; i <= n; ++i) {
if (!vis[i]) {
vis[i] = 1;
for (int j : G[i]) {
if (vis[j]) continue;
++tot;
T[tot].emplace_back(i);
T[i].emplace_back(tot);
dfs2(j, tot);
}
}
}
}
}