【HDU 2586 How far away ?】 邻接表+dfs+LCA(最近公共祖先问题)
2012-12-04 00:11
447 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586
题目大意:有一棵n个节点n-1条边的树。然后给你两个点u,v,让你求u到v的距离。
解题思路:
m询问次数比较小,算一下时间复杂度。用邻接表+bfs完全可以过。
会的就不写了,这里我用邻接表+dfs+LCA。做的最近公共祖先第一题。可做模板。 感谢袁神!!!
题目大意:有一棵n个节点n-1条边的树。然后给你两个点u,v,让你求u到v的距离。
解题思路:
m询问次数比较小,算一下时间复杂度。用邻接表+bfs完全可以过。
会的就不写了,这里我用邻接表+dfs+LCA。做的最近公共祖先第一题。可做模板。 感谢袁神!!!
#pragma comment(linker, "/STACK:1024000000,1024000000") /// hdu可以用这个操作防止栈溢出,强大~ #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <algorithm> #include <cstring> using namespace std; const int maxn=40005; int n; struct Node{ int v, w; Node(int v_, int w_){ v= v_, w= w_; } }; vector<Node>vt[maxn]; /// 用数组的话肯定存不下的,所以用vector int dep[maxn]; /// 记录每个节点离根节点的深度 int father[maxn]; /// 记录上一节点 int dis[maxn]; /// 记录离根节点的距离 void dfs(int u, int fa, int deep){ father[u]= fa; dep[u]= deep; for(int i=0; i<vt[u].size(); ++i){ int v= vt[u][i].v; if( v==fa ) continue; ///特判一下与父节点相连的边,防止进入死循环 dis[v]= dis[u]+vt[u][i].w; dfs( v, u, deep+1 ); } } int p[maxn][30]; void Init_LCA(){ ///因为自己的父节点已经dfs找出来了,所以进行打表 for(int j=0; (1<<j)<=n; ++j) for(int i=1; i<=n; ++i) p[i][j]= -1; for(int i=1; i<=n; ++i) p[i][0]= father[i]; for(int j=1; (1<<j)<=n; ++j) ///以2的指数形式进行操作 for(int i=1; i<=n; ++i) if( p[i][j-1] != -1 ) p[i][j]= p[ p[i][j-1] ][ j-1 ]; ///这一步最关键了 } int LCA(int x, int y){ if( dep[x] < dep[y] ) swap( x, y ); int i, lg; for(lg=0; (1<<lg)<=dep[x]; ++lg); --lg; for(i=lg; i>=0; --i) /// 达到同一水平线上(也就是同一rank值); if( dep[x] - (1<<i) >= dep[y] ) x= p[x][i]; if( x==y ) return x; /// x,y在同一水平线上,使x,y以相同的步进速度往上走,直到达到LCA处; for(i=lg; i>=0 ;--i) if( p[x][i]!=-1 && p[x][i]!=p[y][i] ) x= p[x][i], y= p[y][i]; return father[x]; } int main() { int m, T, u, v, c; cin >> T; while(T--) { for(int i=0; i<=n; i++) vt[i].clear(); cin>>n>>m; for(int i=1; i<n; ++i){ int x, y, w; scanf("%d%d%d", &x,&y,&w); vt[x].push_back( Node( y, w ) ); ///直接存入Node,这样就把点和边一起存进去了 vt[y].push_back( Node( x, w ) ); } dis[1]= 0; dfs(1, -1, 0); Init_LCA(); while(m--){ int x, y; scanf("%d%d", &x, &y); printf("%d\n", dis[x] + dis[y] - 2*dis[ LCA(x, y) ]); ///x到y的距离为x到根节点的距离加上y到根节点的距离减去两倍的最近公共祖先节点到根节点的距离 } } }
相关文章推荐
- hdu 2586 How far away ? LCA 最近公共祖先
- hdu 2874 Connections between cities(最近公共祖先(LCA))
- LCA(最近公共祖先)问题
- 1 数据结构类-最近公共祖先LCA问题
- 1 数据结构类-最近公共祖先LCA问题
- HDU 2586 How far away ? (LCA最近公共祖先)
- hdu 2586(最近公共祖先LCA)
- HDU 2586 How far away ?(LCA模板 最近公共祖先啊)
- 1 数据结构类-最近公共祖先LCA问题
- 最近公共祖先LCA问题(转)
- 第三十九章:最近公共祖先LCA问题
- hdu 2586How far away ? 最近公共祖先LCA离线算法
- 1 数据结构类-最近公共祖先LCA问题
- 最近公共祖先LCA问题
- 学习记录4:LCA (最近公共祖先)(hdu 2586 How far away?)
- ACM: 最近公共祖先问题LCA 图论题 …
- Hdu 5454,Minimum Cut,最近公共祖先+dfs遍历
- 1 数据结构类-最近公共祖先LCA问题
- Timus 1329. Galactic History。LCA最近公共祖先或dfs递归离线处理!
- LCA(最近公共祖先)--tarjan离线算法 hdu 2586