模板最近的共同祖先
LCA tarjan 离线算法
#include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 40010; int first[maxn], head[maxn], cnt, sum; struct edge { int u, v, w, next; }e[maxn*2], qe[maxn], Q[maxn]; int ans[maxn]; int f[maxn], vis[maxn]; int d[maxn]; void AddEdge(int u, int v, int w) { e[cnt].u = u; e[cnt].v = v; e[cnt].w = w; e[cnt].next = first[u]; first[u] = cnt++; e[cnt].u = v; e[cnt].v = u; e[cnt].w = w; e[cnt].next = first[v]; first[v] = cnt++; } int find(int x) { if(f[x] != x) return f[x] = find(f[x]); return f[x]; } void LCA(int u, int k) { f[u] = u; d[u] = k; vis[u] = true; for(int i = first[u]; i != -1; i = e[i].next) { int v = e[i].v; if(vis[v]) continue; LCA(v, k + e[i].w); f[v] = u; } for(int i = head[u]; i != -1; i = qe[i].next) { int v = qe[i].v; if(vis[v]) { ans[qe[i].w] = find(v); } } }
LCA 转RMQ的在线算法
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 200010; struct edge { int u, v, w, next; }edges[maxn*2], e[maxn]; int E[maxn*2], H[maxn*2], I[maxn*2], L[maxn], R[maxn]; int dp[maxn*2][40]; int cnt, clock, dfn; int first[maxn]; int a[maxn<<2]; int b[maxn]; int add[maxn<<2]; int degree[maxn]; int vis[maxn]; void AddEdge(int u, int v, int w) { edges[cnt].u = u; edges[cnt].v = v; edges[cnt].w = w; edges[cnt].next = first[u]; first[u] = cnt++; edges[cnt].u = v; edges[cnt].v = u; edges[cnt].w = w; edges[cnt].next = first[v]; first[v] = cnt++; } void dfs(int u, int fa, int dep) { E[++clock] = u; H[clock] = dep; I[u] = clock; L[u] = ++dfn; b[dfn] = u; for(int i = first[u]; i != -1; i = edges[i].next) { int v = edges[i].v; if(v == fa) continue; if(vis[v]) continue; vis[v] = true; dfs(v, u, dep+1); E[++clock] = u; H[clock] = dep; } R[u] = dfn; } void RMQ_init(int n) { for(int i = 1; i <= n; i++) dp[i][0] = i; for(int j = 1; (1<<j) <= n; j++) for(int i = 1; i+(1<<j)-1 <= n; i++) { if(H[dp[i][j-1]] < H[dp[i+(1<<(j-1))][j-1]]) dp[i][j] = dp[i][j-1]; else dp[i][j] = dp[i+(1<<(j-1))][j-1]; } } int RMQ(int l, int r) { l = I[l], r = I[r]; if(l > r) swap(l, r); int len = r-l+1, k = 0; while((1<<k) <= len) k++; k--; if(H[dp[l][k]] < H[dp[r-(1<<k)+1][k]]) return E[dp[l][k]]; else return E[dp[r-(1<<k)+1][k]]; }
LCA倍增法
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 20010; const int INF = 999999999; int anc[maxn][16], maxcost[maxn][16]; int fa[maxn], L[maxn], cost[maxn], vis[maxn]; int n, m; int first[maxn], cnt; struct edge { int u, v, next; }e[maxn*2]; void AddEdge(int u, int v) { e[cnt].v = v; e[cnt].next = first[u]; first[u] = cnt++; e[cnt].v = u; e[cnt].next = first[v]; first[v] = cnt++; } void pre() { for(int i = 1; i <= n; i++) { anc[i][0] = fa[i]; maxcost[i][0] = cost[i]; for(int j = 1; (1<<j) < n; j++) anc[i][j] = -1; } for(int j = 1; (1<<j) < n; j++) for(int i = 1; i <= n; i++) if(anc[i][j-1] != -1) { int a = anc[i][j-1]; anc[i][j] = anc[a][j-1]; maxcost[i][j] = max(maxcost[i][j-1], maxcost[a][j-1]); } } int query(int p, int q) { int tmp, log, i; if(L[p] < L[q]) swap(p, q); for(log = 1; (1<<log) <= L[p]; log++); log--; int ans = -INF; for(int i = log; i >= 0; i--) if(L[p] - (1<<i) >= L[q]) { ans = max(ans, maxcost[p][i]); p = anc[p][i]; } if(p == q) return ans; for(int i = log; i >= 0; i--) { if(anc[p][i] != -1 && anc[p][i] != anc[q][i]) { ans = max(ans, maxcost[p][i]); ans = max(ans, maxcost[q][i]); p = anc[p][i]; q = anc[q][i]; } } ans = max(ans, cost[p]); ans = max(ans, cost[q]); return ans; } void dfs(int u) { for(int i = first[u]; i != -1; i = e2[i].next) { int v = e[i].v; if(vis[v]) continue; vis[v] = 1; fa[v] = u; L[v] = L[u]+1; dfs(v); } }
版权声明:本文博主原创文章。博客,未经同意不得转载。