poj1986 (LCA)

poj1986

给我们一棵树,求任意两个点之间的距离

dist[a->b] = dist[a] +dist[b] - 2*lca(a,b)

要建双向边,数据可能不是严格意义上的树

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <string>
 12 #include <math.h>
 13 using namespace std;
 14 #pragma warning(disable:4996)
 15 typedef long long LL;
 16 const int INF = 1<<30;
 17 /*
 18
 19 */
 20 struct Edge
 21 {
 22     int to,dist;
 23 };
 24 const int MAX_LOG_V = 100;
 25 const int MAX_V = 100000+10;
 26 int parent[MAX_LOG_V][MAX_V];
 27 int depth[MAX_V];
 28 int dist[MAX_V];
 29 vector<Edge> g[MAX_V];
 30 void dfs(int u, int fa, int d)
 31 {
 32     parent[0][u] = fa;
 33     depth[u] = d;
 34     for(int i=0; i<g[u].size(); ++i)
 35         if(g[u][i].to!=fa)
 36         {
 37             dist[g[u][i].to] = dist[u] + g[u][i].dist;
 38             dfs(g[u][i].to,u,d+1);
 39         }
 40 }
 41 void init(int root, int n)
 42 {
 43     dfs(root,-1,0);
 44     //预处理出parent
 45     for(int k=0; k+1<MAX_LOG_V; ++k)
 46     {
 47         for(int v=1; v<=n; ++v)
 48         {
 49             if(parent[k][v]<0)
 50                 parent[k+1][v] = -1;
 51             else
 52                 parent[k+1][v] = parent[k][parent[k][v]];
 53         }
 54     }
 55 }
 56 int lca(int u, int v)
 57 {
 58     if(depth[u] < depth[v])
 59         swap(u,v);
 60     //让u和v走到同一生度
 61     for(int k=0; k<MAX_LOG_V; ++k)
 62         if((depth[u]-depth[v])>>k&1)//一个数能分解成多个二进制数相加,所以如果&1 为true,那么就向上走
 63             u = parent[k][u];
 64     if(u==v) return u;
 65     //达到同一深度后,二分搜索lca
 66
 67     for(int k=MAX_LOG_V-1; k>=0; --k)
 68         if(parent[k][v]!=parent[k][u])
 69         {//我们并不知道要向上走多少步,但是只要每次走后,
 70         //parent[k][v]!=parent[k][u],那么这一步就可以向上走,即将要走的步数分解为 1 + 2 + 4 + 8 + ...最后一步将在循环结束后走出
 71             u = parent[k][u];
 72             v = parent[k][v];
 73         }
 74     return parent[0][u];
 75 }
 76
 77 int main()
 78 {
 79     int n,a,m,i,b,t,root,c;
 80     char str[2];
 81     Edge tmp;
 82     while(scanf("%d%d",&n,&m)!=EOF)
 83     {
 84
 85         for(i=1; i<=n; ++i)
 86         {
 87             parent[0][i] = -1;
 88             g[i].clear();
 89         }
 90         for(i=0; i<n-1; ++i)
 91         {
 92             scanf("%d%d%d%s",&a,&b,&c,str);
 93             tmp.to = b;
 94             tmp.dist = c;
 95             g[a].push_back(tmp);
 96             tmp.to = a;
 97             g[b].push_back(tmp);
 98         }
 99         root = 1;
100         dist[root] = 0;
101         init(root,n);
102         scanf("%d",&m);
103         for(i=0; i<m; ++i)
104         {
105             scanf("%d%d",&a,&b);
106             int LCA = lca(a,b);
107             printf("%d\n",dist[a]-dist[LCA] + dist[b]-dist[LCA]);
108         }
109
110
111     }
112
113     return 0;
114 }
时间: 2024-08-06 03:28:06

poj1986 (LCA)的相关文章

POJ1986(LCA应用:求两结点之间距离)

Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 11304   Accepted: 3985 Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifesty

POJ1986 Distance Queries (LCA)

传送门: http://poj.org/problem?id=1986 Distance Queries Time Limit: 2000MS   Memory Limit: 30000K       Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifesty

POJ1986 Distance Queries (LCA)(倍增)

Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 12950   Accepted: 4577 Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifesty

poj-1986 Distance Queries(lca+ST+dfs)

题目链接: Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 11531   Accepted: 4068 Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely l

POJ-1986 Distance Queries(LCA、离线)

Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 14378   Accepted: 5062 Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifesty

学习 LCA&amp;&amp;RMQ

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

LCA&amp;&amp;RMQ问题

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

SZOJ 167 Lca裸题

一道.......一道我改了一周的裸题 无根树建双向边 无根树建双向边 无根树建双向边 重要的事情说三遍(微笑) 还有要开longlong 还有双向边不是双倍边(微笑) 我真是,能把自己气吐血10次就不把自己气吐血9次 [问题描述] 已知一棵nn个点的树,点从1开始标号,树上每条边都有一个正整数边权. 有qq个询问,每个询问由type,u,vtype,u,v三个正整数构成. 当type=1type=1时,询问uu到vv路径上所有边权的二进制异或和. 当type=2type=2时,询问uu到vv路