板子

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);
			}
		}
	}
}	

}
posted @ 2023-08-20 22:07  zzzYheng  阅读(79)  评论(0编辑  收藏  举报