LCA+RMQ求树中两点距离
来源:互联网 发布:网络分线器怎么用 编辑:程序博客网 时间:2024/05/16 17:15
题目
H:Distance Queries
- 查看
- 提交
- 统计
- 提问
- 总时间限制:
- 2000ms
- 单个测试点时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He therefore wants to find a path of a more reasonable length. The input to this problem consists of the same input as in "Navigation Nightmare",followed by a line containing a single integer K, followed by K "distance queries". Each distance query is a line of input containing two integers, giving the numbers of two farms between which FJ is interested in computing distance (measured in the length of the roads along the path between the two farms). Please answer FJ's distance queries as quickly as possible!
- 输入
- * Line 1: Two space-separated integers: N and M
* Lines 2..1+M: Each line contains four space-separated entities, F1, F2, L, and D that describe a road. F1 and F2 are numbers of two farms connected by a road, L is its length, and D is a character that is either 'N', 'E', 'S', or 'W' giving the direction of the road from F1 to F2
* Line 2+M: A single integer, K. 1 <= K <= 10,000
* Lines 3+M..2+M+K: Each line corresponds to a distance query and contains the indices of two farms.
(1 <= M < 40,000) - 输出
- * Lines 1..K: For each distance query, output on a single line an integer giving the appropriate distance.
- 样例输入
7 61 6 13 E6 3 9 E3 5 7 S4 1 3 N2 4 20 W4 7 2 S31 61 42 6
- 样例输出
13336
- 提示
- Farms 2 and 6 are 20+3+13=36 apart.
/*DFS + RMQ 在线算法求树中两点之间的距离 */#include<iostream>#include<stdio.h>#include<stdlib.h>#include<vector>#include<queue>#include<string>#include<string.h>#include<map>#include<math.h>#define N 100100using namespace std;struct node{int x,d,next;}edge[2*N];int tot;int head[N];//vector<node> G[N];int E[2*N];//dfs时记录的节点,每条边记录2遍,共记录2*N-1个节点 int D[2*N];//表示dfs记录路径的各个点的深度 int first[N];//first[i]表示记录路径中第一次访问i点的位置下标 int vis[N];//是否访问过 int dis[N];//记录距离根节点的距离 int n,m,top;//top表示数组下标 int dp[30][2*N];//dp[i][j]表示从j点开始,数2^i个点区间内的最大值或最小值,在此题中记录的为最小深度 bool flag[N];void addedge(int u,int v, int w){edge[tot].x=v;edge[tot].d=w;edge[tot].next=head[u];head[u]=tot++;}void dfs(int u,int dep, int w)//正在访问的点u,该点的深度dep,距离根节点的最短路径w {vis[u]=1; E[top]=u;D[top]=dep;first[u]=top++;dis[u]=w;for(int i=head[u];i!=-1;i=edge[i].next){if(!vis[edge[i].x]){int v=edge[i].x;int cost=edge[i].d;dfs(v,dep+1,w+cost);E[top]=u;D[top++]=dep;//回溯时再次访问该点,记录下来 }}/* for(int i=0;i<G[u].size();i++){if(!vis[G[u][i].x]){int v=G[u][i].x;int cost=G[u][i].d;dfs(v,dep+1,w+cost);E[top]=u;D[top++]=dep;//回溯时再次访问该点,记录下来 }}*/ }void ST(int num){//动态规划记录各个区间,及两个点的最近公共祖先所在位置即E和D的下标 for(int i=1;i<=num;i++) dp[0][i]=i;//当长度为 1,起点为 i 时,最近公共祖先为本身//外循环必须为区间长度,先求出区间长度为1的值才能求出区间长度为2的值,依次类推//内循环为起点 for(int i=1;(1<<i)<=num;i++){for( int j=1;j<=num;j++){if(j+(1<<i)-1 <= num)//区间的右端点必须不大于最大值,1<<i (i=0,1,2,3...时,该值为1,2,4,8... ){int a=dp[i-1][j];int b=dp[i-1][j+(1<<i>>1)];//右半个区间,1<<i>>1相当于2^(i-1)if(D[a]<D[b]) dp[i][j]=a;else dp[i][j]=b; }} } } int RMQ(int x,int y){//查询 :求区间x和y之间的最近公共祖先所在位置 //因为区间长度永远是2^i,所以要将查询区间先进行划分 //int k=(int) log(y-x+1.0)/log(2);int k=0;while(1<<(k+1)<=y-x+1) k++;//注意这个地方!!! int a=dp[k][x];int b=dp[k][y-(1<<k)+1];if(D[a]<D[b]) return a;return b; }int main(){while(scanf("%d%d",&n,&m)!=EOF){memset(dis,0,sizeof(dis));memset(first,0,sizeof(first));memset(E,0,sizeof(E));memset(D,0,sizeof(D));memset(vis,0,sizeof(vis));memset(head,-1,sizeof(head));memset(flag,0,sizeof(flag));memset(dp,0,sizeof(dp));tot=0;top=0; int a,b,w; char ch; //node tmp; while(m--) { scanf("%d%d%d %c",&a,&b,&w,&ch); /*tmp.x=b; G[a].push_back(tmp); tmp.x=a; G[b].push_back(tmp); */ addedge(a,b,w);addedge(b,a,w); flag[b]=1; //无向图 }int root;for(int i=1;i<=n;i++){if(!flag[i]){ root=i; break;}}dfs(root,0,0);ST(top-1);int k;scanf("%d",&k);while(k--){scanf("%d%d",&a,&b);int x=first[a];int y=first[b];if(x>y) swap(x,y);int pos=RMQ(x,y);printf("%d\n",dis[a]+dis[b]-2*dis[E[pos]]);} }return 0;}
0 0
- LCA+RMQ求树中两点距离
- POJ 2874 LCA 树上任意两点距离
- hdu 2586 How far away ?(LCA 求两点距离)
- poj 1986 Distance Queries(LCA求两点距离模版)
- POJ 1986 Distance Queries LCA树上两点的距离
- POJ 1986 Distance Queries(查询两点距离,LCA)
- lca&rmq
- 【RMQ & LCA】
- RMQ && LCA
- LCA+RMQ
- LCA && RMQ
- LCA+RMQ
- LCA&RMQ
- LCA&RMQ
- LCA&&RMQ
- 两点距离
- 两点距离
- 两点距离
- 【mysql】事务死锁问题
- Android之利用android:indeterminateDrawable来实现ProgressBar三种方式
- 视图和表
- mysql主从复制原理
- 第二周-项目1C/C++语言中函数参数传递的三种方式
- LCA+RMQ求树中两点距离
- POJ 2112 Optimal Milking 网络流初步
- Spark shuffle 优化
- 第四周《C语言及程序设计》实践项目22 用指针法访问数组元素
- 工作一年两个月了~
- MATLAB矩阵压缩函数squeeze
- Android剪切板(ClipboardManager) 复制文本
- light oj 1013 迷之ac...我不知道为什么不re
- Android实现Filterable通过输入文本框实现联系人自动筛选