POJ 1986:Distance Queries(倍增求LCA)

http://poj.org/problem?id=1986

题意:给出一棵n个点m条边的树,还有q个询问,求树上两点的距离。

思路:这次学了一下倍增算法求LCA。模板。

dp[i][j]代表第i个点的第2^j个祖先是哪个点,dp[i][0] = i的第一个祖先 = fa[i]。转移方程:dp[i][j] = dp[dp[i][j-1][j-1]。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 using namespace std;
 6 #define N 100010
 7 struct Edge {
 8     int v, nxt, w;
 9     Edge () {}
10     Edge (int v, int nxt, int w) : v(v), nxt(nxt), w(w) {}
11 } edge[N];
12 int dp[N][30], dep[N], dis[N], fa[N], head[N], tot, n;
13
14 void Add(int u, int v, int w) {
15     edge[tot] = Edge(v, head[u], w); head[u] = tot++;
16     edge[tot] = Edge(u, head[v], w); head[v] = tot++;
17 }
18
19 void DFS(int u) {
20     dp[u][0] = fa[u];
21     for(int i = 1; i <= 20; i++) // 转移
22         dp[u][i] = dp[dp[u][i-1]][i-1];
23     for(int i = head[u]; ~i; i = edge[i].nxt) {
24         int v = edge[i].v;
25         if(v == fa[u]) continue;
26         fa[v] = u;
27         dep[v] = dep[u] + 1;
28         dis[v] = dis[u] + edge[i].w;
29         DFS(v);
30     }
31 }
32
33 int LCA(int x, int y) {
34     if(dep[x] < dep[y]) swap(x, y); //设x为较深的点
35     for(int i = 20; i >= 0; i--) // 让x跑到和y同一深度
36         if(dep[dp[x][i]] >= dep[y]) x = dp[x][i];
37     if(x == y) return x;
38     for(int i = 20; i >= 0; i--) // x和y同时向上跑
39         if(dp[x][i] != dp[y][i])
40             x = dp[x][i], y = dp[y][i];
41     return dp[x][0];
42 }
43
44 int main() {
45     int m, q;
46     while(~scanf("%d%d", &n, &m)) {
47         memset(dp, 0, sizeof(dp));
48         memset(dis, 0, sizeof(dis));
49         memset(dep, 0, sizeof(dep));
50         memset(head, -1, sizeof(head));
51         tot = 0; char s[4];
52         for(int i = 0; i < m; i++) {
53             int u, v, w;
54             scanf("%d%d%d%s", &u, &v, &w, s);
55             Add(u, v, w);
56         }
57         fa[1] = 1; dis[1] = dep[1] = 0;
58         DFS(1);
59         scanf("%d", &q);
60         while(q--) {
61             int u, v;
62             scanf("%d%d", &u, &v);
63             printf("%d\n", dis[u] + dis[v] - dis[LCA(u, v)] * 2);
64         }
65     }
66     return 0;
67 }
时间: 2024-08-03 03:11:55

POJ 1986:Distance Queries(倍增求LCA)的相关文章

poj 1986 Distance Queries 带权lca 模版题

Distance Queries Description 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

POJ 1986 Distance Queries LCA两点距离树

标题来源:POJ 1986 Distance Queries 意甲冠军:给你一棵树 q第二次查询 每次你问两个点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + dis(root,v) - 2*dis(roor,LCA(u,v)) 求近期公共祖先和dis数组 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int max

POJ 1986 Distance Queries LCA树上两点的距离

题目来源:POJ 1986 Distance Queries 题意:给你一颗树 q次询问 每次询问你两点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + dis(root,v) - 2*dis(roor,LCA(u,v)) 求最近公共祖先和dis数组 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn =

POJ 1986 Distance Queries 【输入YY &amp;&amp; LCA(Tarjan离线)】

任意门:http://poj.org/problem?id=1986 Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 16648   Accepted: 5817 Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much t

poj 1986 Distance Queries LCA

题目链接:http://poj.org/problem?id=1986 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

POJ 1986 Distance Queries (在线LCA转RMQ)

题目地址:POJ 1986 纯模板题.输入的最后一个字母是多余的,完全不用管.还有注意询问的时候有相同点的情况. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set>

POJ 1986 Distance Queries(LCA)

[题目链接] http://poj.org/problem?id=1986 [题目大意] 给出一棵树,问任意两点间距离. [题解] u,v之间距离为dis[u]+dis[v]-2*dis[LCA(u,v)] [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=300010; int d[N],num[N],dis[N],ed=0,x

POJ 1986 Distance Queries

http://poj.org/problem?id=1986 题意:一棵树里找到两个点的距离.(不用考虑不联通的情况) 题解:LCA模板题. 1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <string> 5 #include <cstdio> 6 #include <cmath> 7 #include <queue>

POJ - 1986 Distance Queries(离线Tarjan算法)

1.一颗树中,给出a,b,求最近的距离.(我没考虑不联通的情况,即不是一颗树的情况) 2.用最近公共祖先来求, 记下根结点到任意一点的距离dis[],这样ans = dis[u] + dis[v] - 2 * dis[lca(u, v)] 3. /* 离线算法,LCATarjan 复杂度O(n+Q); */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const

HDU 4081 Qin Shi Huang&#39;s National Road System 最小生成树+倍增求LCA

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081 Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5428    Accepted Submission(s): 1902 Problem Description