[POJ1330]Nearest Common Ancestors(LCA, 离线tarjan)
2016-05-20 11:47
393 查看
题目链接:http://poj.org/problem?id=1330
题意就是求一组最近公共祖先,昨晚学了离线tarjan,今天来实现一下。
个人感觉tarjan算法是利用了dfs序和节点深度的关系,大致的意思:dfs如果不递归到递归基,那么dfs就会越递归越深,这个时候深度也是相应增加的,所以这个时候任意在已经遍历过的节点中选取两个点,计算他们的lca也就相当于是用并查集求他们的root。而dfs执行到递归基,转而执行下一个分支的时候,这个时候dfs的节点应当是小于等于之前执行到递归基的节点(叶节点)的深度的,此时再更新并查集那就自然不是和之前比此节点深度更深的节点的root了,因为那些root有可能比此点更低。
题意就是求一组最近公共祖先,昨晚学了离线tarjan,今天来实现一下。
个人感觉tarjan算法是利用了dfs序和节点深度的关系,大致的意思:dfs如果不递归到递归基,那么dfs就会越递归越深,这个时候深度也是相应增加的,所以这个时候任意在已经遍历过的节点中选取两个点,计算他们的lca也就相当于是用并查集求他们的root。而dfs执行到递归基,转而执行下一个分支的时候,这个时候dfs的节点应当是小于等于之前执行到递归基的节点(叶节点)的深度的,此时再更新并查集那就自然不是和之前比此节点深度更深的节点的root了,因为那些root有可能比此点更低。
/* ━━━━━┒ギリギリ♂ eye! ┓┏┓┏┓┃キリキリ♂ mind! ┛┗┛┗┛┃\○/ ┓┏┓┏┓┃ / ┛┗┛┗┛┃ノ) ┓┏┓┏┓┃ ┛┗┛┗┛┃ ┓┏┓┏┓┃ ┛┗┛┗┛┃ ┓┏┓┏┓┃ ┛┗┛┗┛┃ ┓┏┓┏┓┃ ┃┃┃┃┃┃ ┻┻┻┻┻┻ */ #include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; #define fr first #define sc second #define cl clear #define BUG puts("here!!!") #define W(a) while(a--) #define pb(a) push_back(a) #define Rint(a) scanf("%d", &a) #define Rll(a) scanf("%lld", &a) #define Rs(a) scanf("%s", a) #define Cin(a) cin >> a #define FRead() freopen("in", "r", stdin) #define FWrite() freopen("out", "w", stdout) #define Rep(i, len) for(int i = 0; i < (len); i++) #define For(i, a, len) for(int i = (a); i < (len); i++) #define Cls(a) memset((a), 0, sizeof(a)) #define Clr(a, x) memset((a), (x), sizeof(a)) #define Full(a) memset((a), 0x7f7f, sizeof(a)) #define lrt rt << 1 #define rrt rt << 1 | 1 #define pi 3.14159265359 #define RT return typedef long long LL; typedef long double LD; typedef unsigned long long ULL; typedef pair<int, int> pii; typedef pair<string, int> psi; typedef map<string, int> msi; typedef vector<LL> vl; typedef vector<vl> vvl; typedef vector<bool> vb; const int maxn = 10010; int n, in[maxn]; vector<int> G[maxn]; int pre[maxn]; bool vis[maxn]; int u, v; int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); } void unite(int x, int y) { x = find(x); y = find(y); if(x != y) pre[y] = x; } void dfs(int u) { pre[u] = u; Rep(i, G[u].size()) { if(!vis[G[u][i]]) { dfs(G[u][i]); unite(u, G[u][i]); } } vis[u] = 1; if(u == ::u && vis[::v]) printf("%d\n", find(::v)); if(u == ::v && vis[::u]) printf("%d\n", find(::u)); } int main() { // FRead(); int T; Rint(T); W(T) { Cls(in); Cls(vis); Rep(i, maxn) G[i].clear(); Rint(n); Rep(i, n-1) { Rint(u); Rint(v); G[u].push_back(v); in[v]++; } Rint(u); Rint(v); For(i, 1, n+1) if(!in[i]) dfs(i); } RT 0; }
相关文章推荐
- 简单两步搞定小米路由新增功能-DDNS
- oracle一个创建用户、创建表空间、授权、建表的完整过程
- Linux 平台下 MySQL 5.5 安装 说明 与 示例
- 11.UILable
- Android异步更新UI的四种方式
- 对hibernate.hbm2ddl.auto配置的总结
- 关于zxing二维码扫描 远距离扫描才能成功
- closest pair of points(O(n*logn*logn)) solution
- Spring 实例入门
- mybatis多参数传递(其中包括数组)
- opencv打开多个摄像头同时预览
- JavaScript-学习一字符串
- SpringMVC中使用Interceptor拦截器
- MySQL 发展史
- hdu 3003 Pupu
- 记录阿里云被肉鸡的破解方法
- 调试器如何工作(1)
- Caffe学习2--Blobs,Layers与Nets
- C语言宏定义的简单总结
- 不管你以后写不写JS,都应该学会这种思考方式