概念
算法
ST算法(在线)
#include <cstdio>
#include <cstring>
const int MAXNODE = 100010;
const int MAXEDGE = 200010;
struct Edge {
int u, v, next;
Edge() {}
Edge(int u, int v, int next): u(u), v(v), next(next) {}
};
struct ST {
Edge edges[MAXEDGE];
int n, m, tot;
int head[MAXNODE], depth[MAXNODE], first[MAXNODE], ver[MAXNODE];
int dp[MAXNODE][64];
bool vis[MAXNODE];
void init(int n) {
this->n = n;
m = tot = 0;
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
}
void AddEdge(int u, int v) {
edges[m] = Edge(u, v, head[u]);
head[u] = m++;
}
//ver记录的是第tot个结点是哪个,first记录的是结点u第一次出现的位置,depth记录的是第tot个结点的深度
void dfs(int u, int dep) {
vis[u] = true; ver[++tot] = u; first[u] = tot; depth[tot] = dep;
for (int i = head[u]; ~i; i = edges[i].next) {
int v = edges[i].v;
if (!vis[v]) {
dfs(v, dep + 1);
ver[++tot] = u; depth[tot] = dep;
}
}
}
void RMQ() {
//dp记录的是下标从i开始,长度为2的j次方这段区间内深度最小的点是ver中的第几个
for (int i = 1; i <= tot; i++)
dp[i][0] = i;
int a, b;
for (int j = 1; (1 << j) <= tot; j++)
for (int i = 1; i + (1 << j) - 1 <= tot; i++) {
a = dp[i][j - 1];
b = dp[i + (1 << (j - 1))][j - 1];
if (depth[a] < depth[b])
dp[i][j] = a;
else
dp[i][j] = b;
}
}
void solve(int root) {
dfs(root, 1);
RMQ();
}
//查询区间[x,y]中深度最小的那个数的位置
int Query(int x, int y) {
int k = 0;
while (1 << (k + 1) <= y - x + 1) k++;
int a = dp[x][k];
int b = dp[y - (1 << k) + 1][k];
if (depth[a] < depth[b]) return a;
return b;
}
int LCA(int x, int y) {
x = first[x];
y = first[y];
if (x > y) {
x = x ^ y; y = x ^ y; x = x ^ y;
}
int c = Query(x, y);
return ver[c];
}
}st;
int main() {
return 0;
}
tarjan离线算法
#include <cstdio>
#include <cstring>
const int MAXNODE = 40010;
const int MAXEDGE = 80010;
typedef int Type;
const Type INF = 0x3f3f3f3f; //1e20
struct Edge{
int u, v, next;
Type dis;
Edge() {}
Edge(int u, int v, int next, Type dis): u(u), v(v), next(next), dis(dis) {}
};
struct Question{
int u, v, next;
bool ok;
Question() {}
Question(int u, int v, int next): u(u), v(v), next(next), ok(false){}
};
struct Tarjan{
Edge edges[MAXEDGE];
Question ques[MAXNODE];
int n, m, q;
int EdgeHead[MAXNODE], f[MAXNODE], LCA[MAXNODE], QuesHead[MAXNODE];
bool vis[MAXNODE];
Type dis[MAXNODE];
void init(int n) {
this->n = n;
m = q = 0;
memset(vis, 0, sizeof(vis));
memset(EdgeHead, -1, sizeof(EdgeHead));
memset(QuesHead, -1, sizeof(QuesHead));
memset(LCA, 0, sizeof(LCA));
}
void AddEdge(int u, int v, Type dis) {
edges[m] = Edge(u, v, EdgeHead[u], dis);
EdgeHead[u] = m++;
}
void AddQues(int x, int y) {
ques[q] = Question(x, y, QuesHead[x]);
QuesHead[x] = q++;
}
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
//tarjan,遍历u结点的所有结点,并将u结点的所有直系子节点的父亲设为u,再进行查询
void dfs(int u) {
f[u] = u;
vis[u] = true;
for (int i = EdgeHead[u]; ~i; i = edges[i].next) {
int v = edges[i].v;
if (!vis[v]) {
dis[v] = dis[u] + edges[i].dis;
dfs(v);
f[v] = u;
}
}
//查询,如果其中一个结点刚好是u,且另一个结点已经遍历过,则u和v的LCA就是f[v]
for (int i = QuesHead[u]; ~i; i = ques[i].next) {
if (ques[i].ok) continue;
int v = ques[i].v;
if (vis[v]) {
LCA[i] = find(v);
ques[i].ok = ques[i ^ 1].ok = true;
}
}
}
}tarjan;
int main() {
return 0;
}
题目
HDU - 2460 Network 边双连通+LCA
HDU - 2586 How far away ?LCA模版题
HDU - 2874 Connections between cities 森林+LCA
HDU - 3078 Network
POJ - 2763 Housewife Wind LCA+暴力
POJ - 3728 The merchant dp+LCA(好题)
POJ - 3417 Network LCA+dp
POJ - 1986 Distance Queries LCA模版
POJ - 1330 Nearest Common Ancestors LCA模版
POJ - 1470 Closest Common Ancestors LCA模版
SPOJ - QTREE2 Query on a tree II 暴力+LCA
UVALive - 4960 Sensor network 生成树+LCA
UVA - 11354 Bond 生成树+LCA