LCA入门题集小结
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586
题目:
How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 21500 Accepted Submission(s): 8471
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
#include <cstdio>
#include <vector>
using namespace std; const int maxn = 4e4 + ;
int n, m, u, v, k;
int fa[maxn][], deep[maxn], cost[maxn]; struct edge {
int v, l;
edge(int v = , int l = ) : v(v), l(l) {}
}; vector<edge> G[maxn]; void dfs(int u, int d, int p) {
deep[u] = d;
fa[u][] = p;
for(int i = ; i < G[u].size(); i++) {
int v = G[u][i].v;
if(v != p) {
cost[v] = cost[u] + G[u][i].l;
dfs(v, d + , u);
}
}
} void lca() {
for(int i = ; i <= n; i++) {
for(int j = ; ( << j) <= n; j++) {
fa[i][j] = -;
}
}
for(int j = ; ( << j) <= n; j++) {
for(int i = ; i <= n; i++) {
if(fa[i][j-] != -) {
fa[i][j] = fa[fa[i][j-]][j-];
}
}
}
} int query(int u, int v) {
if(deep[u] < deep[v]) swap(u, v);
int k;
for(k = ; ( << (k + )) <= deep[u]; k++);
for(int i = k; i >= ; i--) {
if(deep[u] - ( << i) >= deep[v]) {
u = fa[u][i];
}
}
if(u == v) return u;
for(int i = k; i >= ; i--) {
if(fa[u][i] != - && fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][];
} int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
G[i].clear();
}
for(int i = ; i < n; i++) {
scanf("%d%d%d", &u, &v, &k);
G[u].push_back(edge(v, k));
G[v].push_back(edge(u, k));
}
dfs(, , -);
lca();
while(m--) {
scanf("%d%d", &u, &v);
printf("%d\n", cost[u] + cost[v] - * cost[query(u, v)]);
}
}
return ;
}
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874
题目:
Connections between cities
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13879 Accepted Submission(s): 3159
Now, your task comes. After giving you the condition of the roads, we want to know if there exists a path between any two cities. If the answer is yes, output the shortest path between them.
Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 15827 | Accepted: 5576 | |
Case Time Limit: 1000MS |
Description
Input
* 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.
Output
Sample Input
7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6
Sample Output
13
3
36
Hint
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std; const int maxn = 1e5 + ;
int n, m, q, u, v, k;
int fa[maxn][], deep[maxn], cost[maxn]; struct edge {
int v, l;
edge(int v = , int l = ) : v(v), l(l) {}
}; vector<edge> G[maxn]; void dfs(int u, int d, int p) {
deep[u] = d;
fa[u][] = p;
for(int i = ; i < G[u].size(); i++) {
int v = G[u][i].v;
if(v != p) {
cost[v] = cost[u] + G[u][i].l;
dfs(v, d + , u);
}
}
} void lca() {
for(int i = ; i <= n; i++) {
for(int j = ; ( << j) <= n; j++) {
fa[i][j] = -;
}
}
for(int j = ; ( << j) <= n; j++) {
for(int i = ; i <= n; i++) {
if(fa[i][j-] != -) {
fa[i][j] = fa[fa[i][j-]][j-];
}
}
}
} int query(int u, int v) {
if(deep[u] < deep[v]) swap(u, v);
int k;
for(k = ; ( << ( + k)) <= deep[u]; k++);
for(int i = k; i >= ; i--) {
if(deep[u] - ( << i) >= deep[v]) {
u = fa[u][i];
}
}
if(u == v) return u;
for(int i = k; i >= ; i--) {
if(fa[u][i] != - && fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][];
} int main() {
while(~scanf("%d%d", &n, &m)) {
memset(cost, , sizeof(cost));
for(int i = ; i <= n; i++) {
G[i].clear();
}
for(int i = ; i < m; i++) {
scanf("%d%d%d%*s", &u, &v, &k);
G[u].push_back(edge(v, k));
G[v].push_back(edge(u, k));
}
dfs(, , -);
lca();
scanf("%d", &q);
while(q--) {
scanf("%d%d", &u, &v);
printf("%d\n", cost[u] + cost[v] - * cost[query(u, v)]);
}
}
return ;
}
题目链接:http://poj.org/problem?id=1330
题目:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 32969 | Accepted: 16750 |
Description
In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is.
For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest common ancestor of y and z is y.
Write a program that finds the nearest common ancestor of two distinct nodes in a tree.
Input
Output
Sample Input
2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5
Sample Output
4
3 思路:裸的LCA,不过要注意它的节点之间是有向的,所以需要用一个数组来储存入度,以入度为0的节点做根节点。
代码实现如下:
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std; const int maxn = 1e4 + ;
int t, n, u, v, s;
int deep[maxn], fa[maxn][], in[maxn]; vector<int> G[maxn]; void dfs(int u, int d, int p) {
deep[u] = d;
fa[u][] = p;
for(int i = ; i < G[u].size(); i++) {
int v = G[u][i];
if(v != p) {
dfs(v, d + , u);
}
}
} void lca() {
for(int i = ; i <= n; i++) {
for(int j = ; ( << j) <= n; j++) {
fa[i][j] = -;
}
}
for(int j = ; ( << j) <= n; j++) {
for(int i = ; i <= n; i++) {
if(fa[i][j-] != -) {
fa[i][j] = fa[fa[i][j-]][j-];
}
}
}
} int query(int u, int v) {
if(deep[u] < deep[v]) swap(u, v);
int k;
for(k = ; ( << ( + k)) <= deep[u]; k++);
for(int i = k; i >= ; i--) {
if(deep[u] - ( << i) >= deep[v]) {
u = fa[u][i];
}
}
if(u == v) return u;
for(int i = k; i >= ; i--) {
if(fa[u][i] != - && fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][];
} int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = ; i <= n; i++) {
G[i].clear();
}
memset(in, , sizeof(in));
for(int i = ; i < n; i++) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
in[v]++;
}
for(int i = ; i <= n; i++) {
if(in[i] == ) {
s = i;
break;
}
}
dfs(s, , -);
lca();
scanf("%d%d", &u, &v);
printf("%d\n", query(u, v));
}
return ;
}
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4547
题目:
CD操作
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3035 Accepted Submission(s): 848
这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
2. CD .. (返回当前目录的上级目录)
现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?
每个样例首先一行是两个整数N和M(1<=N,M<=100000),表示有N个目录和M个询问;
接下来N-1行每行两个目录名A B(目录名是只含有数字或字母,长度小于40的字符串),表示A的父目录是B。
最后M行每行两个目录名A B,表示询问将当前目录从A变成B最少要多少次CD操作。
数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
#include <map>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn = 1e5 + ;
int t, n, m, cnt;
string s1, s2;
int cost[maxn], deep[maxn], fa[maxn][], in[maxn]; struct edge {
int v, l;
edge (int v = , int l = ) : v (v), l (l) {}
}; vector<edge> G[maxn];
map<string, int> mp; void init() {
cnt = ;
mp.clear();
memset (in, , sizeof (in) );
memset (cost, , sizeof (cost) );
for (int i = ; i <= n; i++) {
G[i].clear();
}
} void dfs (int u, int d, int p) {
deep[u] = d;
fa[u][] = p;
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i].v;
if (v != p) {
cost[v] = cost[u] + G[u][i].l;
dfs (v, d + , u);
}
}
} void lca() {
for (int i = ; i <= n; i++) {
for (int j = ; ( << j) <= n; j++) {
fa[i][j] = -;
}
}
for (int j = ; ( << j) <= n; j++) {
for (int i = ; i <= n; i++) {
if (fa[i][j - ] != -) {
fa[i][j] = fa[fa[i][j - ]][j - ];
}
}
}
} int query (int u, int v) {
if (deep[u] < deep[v])
swap (u, v);
int k;
for (k = ; ( << ( + k) ) <= deep[u]; k++);
for (int i = k; i >= ; i--) {
if (deep[u] - ( << i) >= deep[v]) {
u = fa[u][i];
}
}
if (u == v)
return u;
for (int i = k; i >= ; i--) {
if (fa[u][i] != - && fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][];
} int main() {
ios::sync_with_stdio (false);
cin.tie ();
cin >> t;
while (t--) {
cin >> n >> m;
init();
for (int i = ; i < n; i++) {
cin >> s1 >> s2;
if(mp.find(s1) == mp.end())
mp[s1] = ++cnt;
if(mp.find(s2) == mp.end())
mp[s2] = ++cnt;
in[mp[s1]]++;
G[mp[s1]].push_back (edge (mp[s2], ) );
G[mp[s2]].push_back (edge (mp[s1], ) );
}
int s;
for (int i = ; i <= n; i++) {
if (in[i] == ) {
s = i;
}
}
dfs (s, , -);
lca();
while (m--) {
cin >> s1 >> s2;
if(query(mp[s1], mp[s2]) == mp[s2]) {
cout <<cost[mp[s1]] - cost[mp[s2]] <<endl;
} else {
cout << cost[mp[s1]] - cost[query (mp[s1], mp[s2])] + << endl;
}
}
}
return ;
}
Time Limit: 1 Second Memory Limit: 32768 KB
Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terrible, that there are traffic jams everywhere. Now, Cerror finds out that the main reason of them is the poor design of the roads distribution, and he want to change this situation.
In order to achieve this project, he divide the city up to N regions which can be viewed as separate points. He thinks that the best design is the one that connect all region with shortest road, and he is asking you to check some of his designs.
Now, he gives you an acyclic graph representing his road design, you need to find out the shortest path to connect some group of three regions.
Input
The input contains multiple test cases! In each case, the first line contian a interger N (1 < N < 50000), indicating the number of regions, which are indexed from 0 to N-1. In each of the following N-1 lines, there are three interger Ai, Bi, Li (1 < Li < 100) indicating there's a road with length Li between region Ai and region Bi. Then an interger Q (1 < Q < 70000), the number of group of regions you need to check. Then in each of the following Q lines, there are three interger Xi, Yi, Zi, indicating the indices of the three regions to be checked.
Process to the end of file.
Output
Q lines for each test case. In each line output an interger indicating the minimum length of path to connect the three regions.
Output a blank line between each test cases.
Sample Input
4
0 1 1
0 2 1
0 3 1
2
1 2 3
0 1 2
5
0 1 1
0 2 1
1 3 1
1 4 1
2
0 1 2
1 0 3
Sample Output
3
2 2
2
思路:将所给的x,y,z分别两两求一次lca,然后除2即可。
代码实现如下:
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std; const int maxn = 5e4 + ;
int n, q, u, v, k;
int cost[maxn], deep[maxn], fa[maxn][]; struct edge {
int v, l;
edge(int v = , int l = ) : v(v), l(l) {}
}; vector<edge> G[maxn]; void init() {
memset(cost, , sizeof(cost));
for(int i = ; i < maxn; i++) {
G[i].clear();
}
} void dfs(int u, int d, int p) {
deep[u] = d;
fa[u][] = p;
for(int i = ; i < G[u].size(); i++) {
int v = G[u][i].v;
if(v != p) {
cost[v] = cost[u] + G[u][i].l;
dfs(v, d + , u);
}
}
} void lca() {
for(int i = ; i < n; i++) {
for(int j = ; ( << j) < n; j++) {
fa[i][j] = -;
}
}
for(int j = ; ( << j) < n; j++) {
for(int i = ; i < n; i++) {
if(fa[i][j-] != -) {
fa[i][j] = fa[fa[i][j-]][j-];
}
}
}
} int query(int u, int v) {
if(deep[u] < deep[v]) swap(u, v);
int k;
for(k = ; ( << k) <= deep[u]; k++);
for(int i = k; i >= ; i--) {
if(deep[u] - ( << i) >= deep[v]) {
u = fa[u][i];
}
}
if(u == v) return u;
for(int i = k; i >= ; i--) {
if(fa[u][i] != - && fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][];
} int main() {
int flag = ;
while(~scanf("%d", &n)) {
if(flag) printf("\n");
flag = ;
init();
for(int i = ; i < n; i++) {
scanf("%d%d%d", &u, &v, &k);
G[u].push_back(edge(v, k));
G[v].push_back(edge(u, k));
}
dfs(, , -);
lca();
scanf("%d", &q);
while(q--) {
scanf("%d%d%d", &u, &v, &k);
printf("%d\n", (cost[u] + cost[v] - * cost[query(u, v)] + cost[u] + cost[k] - * cost[query(u, k)] + cost[v] + cost[k] - * cost[query(v, k)]) / );
}
}
return ;
}
至此感觉自己的LCA应该算是入门了,深入刷难题暑假再开始,毕竟现在要开始准备期末了,免得上学期专业课满绩点,高代全年级第一,这学期全部挂科然后挨骂Σ( ° △ °|||)︴
LCA入门题集小结的更多相关文章
- poj 1330(RMQ&LCA入门题)
传送门:Problem 1330 https://www.cnblogs.com/violet-acmer/p/9686774.html 参考资料: http://dongxicheng.org/st ...
- POJ1330(LCA入门题)
Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 23388 Accept ...
- lca入门———树上倍增法(博文内含例题)
倍增求LCA: father[i][j]表示节点i往上跳2^j次后的节点 可以转移为 father[i][j]=father[father[i][j-1]][j-1] 整体思路: 先比较两个点的深度, ...
- poj 2524:Ubiquitous Religions(并查集,入门题)
Ubiquitous Religions Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 23997 Accepted: ...
- hrbustoj 1073:病毒(并查集,入门题)
病毒Time Limit: 1000 MS Memory Limit: 65536 KTotal Submit: 719(185 users) Total Accepted: 247(163 user ...
- ACM题集以及各种总结大全(转)
ACM题集以及各种总结大全! 虽然退役了,但是整理一下,供小弟小妹们以后切题方便一些,但由于近来考试太多,顾退役总结延迟一段时间再写!先写一下各种分类和题集,欢迎各位大牛路过指正. 一.ACM入门 关 ...
- ACM题集以及各种总结大全!
ACM题集以及各种总结大全! 虽然退役了,但是整理一下,供小弟小妹们以后切题方便一些,但由于近来考试太多,顾退役总结延迟一段时间再写!先写一下各种分类和题集,欢迎各位大牛路过指正. 一.ACM入门 关 ...
- Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)
3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...
- 数位dp题集
题集见大佬博客 不要62 入门题,检验刚才自己有没有看懂 注意一些细节. 的确挺套路的 #include<bits/stdc++.h> #define REP(i, a, b) for(r ...
随机推荐
- 解决ueditor编辑器图片在线管理图片无法显示
使用ueditor,点击在线管理,服务器图片路径显示不正确,如下图所示 查看源码,如下: 发现图片src中中间多了一长串的项目跟路径,解决的办法是 把 jsp/controller.jsp 里面 ...
- opencv图像像素值读取
说到图像像素,肯定要先认识一下图像中的坐标系长什么样. 1. 坐标体系中的零点坐标为图片的左上角,X轴为图像矩形的上面那条水平线:Y轴为图像矩形左边的那条垂直线.该坐标体系在诸如结构体Mat,Rect ...
- shiro学习详解(开篇)
一.前言 要开始接触公司另外一个项目了,RX和我说了下整个项目框架的结构,其中提到权限的控制是通过shiro来处理的,对我而言又是一个全新的知识点,于是今天花了一点时间去学习shiro的使用,看了好几 ...
- 使用Gulp实现网页自动刷新:gulp-connect
入门指南 1. 全局安装 gulp: npm install --global gulp 2. 作为项目的开发依赖(devDependencies)安装: npm install --save-dev ...
- WPF实例,以getFiles()获取文件夹,treeview的应用
读取电脑硬盘根目录添加到TreeView控件 foreach (DriveInfo item in System.IO.DriveInfo.GetDrives()) { if(item.ToStrin ...
- 从一个ListBox中的元素点击导入另一个ListBox元素中
先看效果图:
- BZOJ5190 Usaco2018 Jan Stamp Painting(动态规划)
可以大胆猜想的一点是,只要有不少于一个长度为k的颜色相同子串,方案就是合法的. 直接算有点麻烦,考虑减去不合法的方案. 一个正(xue)常(sha)的思路是枚举序列被分成的段数,问题变为用一些1~k- ...
- vue2.0 自定义时间过滤器
html <td>{{serverInfo.serverTime| formatTime('YMDHMS')}}</td> js serverTime: new Date(). ...
- hdu 1392 Surround the Trees (凸包)
Surround the Trees Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- linq的decimal类型保存到数据库只保存到小数点后两位的问题
今天的一个decimal类型保存到数据的问题困扰了我很长时间,最后就是一个小小的设置问题解决······坑······深坑···· 话不多说,直接说问题,在说答案: 问题:linq当采用EF的DbCo ...