LCA小结
2015-09-13 21:29
337 查看
概念
算法
ST算法(在线)
tarjan离线算法
[b]题目
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
算法
ST算法(在线)
[code]#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) 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离线算法
[code]#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; }
[b]题目
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
相关文章推荐
- 1.ef 映射关系
- 超级课程表原理解析(如何获取网页内容)
- 快速生成xls模板
- 如何解决GDI+渲染图片慢的问题?
- 黑马程序员----反射
- SVM—当样本数小于维度的时候
- Spring MVC + AngularJS Integration
- 获取当前控制器的方法
- hdu5437 Alisha’s Party
- oracle for update
- [LeetCode-2] Add Two Numbers(链表数据之和)
- C语言实现单链表-01版
- Effective C++ —— 实现(五)
- Shell 脚本学习笔记-常用命令
- 多进程、多线程、同步、通信
- 等价类
- 跟我一起写 Makefile
- 跟我一起写 Makefile
- 高性能web服务器nginx(三)之源码搭建LNMP
- linux yum命令详解