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 ...
随机推荐
- python学习第二天-基本数据类型常用方法
1.直入主题 python中基本的数据类型有 数字(整形,长整形,浮点型,复数) 字符串 字节串:在介绍字符编码时介绍字节bytes类型 列表 元组 字典 集合 下面我们直接将以下面几个点进行学习 # ...
- IIS7,IIS7.5 URL重写模块工具
URL 重写模块 2.0 提供基于规则的重写机制,可在 Web 服务器处理请求的 URL 之前对其进行更改,以及在向 HTTP 客户端提供响应内容之前修改响应内容. 注意:使用环境为IIS7.0(x6 ...
- 【week4】课堂Scrum站立会议
项目:连连看游戏 小组名称:天天向上(旁听) 小组成员:张政 张金生 李权 武致远 已完成任务 1.本项目采用c#. 2. 初步界面. 形成一个windows下的游戏界面,每个需要消除的方块是一个bu ...
- (转)NEST.net Client For Elasticsearch简单应用
由于最近的一个项目中的搜索部分要用到 Elasticsearch 来实现搜索功能,苦于英文差及该方面的系统性资料不好找,在实现时碰到了不少问题,现把整个处理过程的代码分享下,给同样摸索的人一些借鉴,同 ...
- 从实战角度浅析snmp
Snmp Simple Network Management Protocol Snmp最终是为五花八门的网管软件服务的,由于接触的网管软件较少,所以对snmp的理解至今还仅限于初级配置阶段.以下言 ...
- 第54天:原生js实现轮播图效果
一.轮播图的原理: 一系列的大小相等的图片平铺,利用CSS布局只显示一张图片,其余隐藏.通过计算偏移量利用定时器实现自动播放,或通过手动点击事件切换图片. 二.Html布局 首先父容器containe ...
- Foundation框架—时间处理对象NSDate
NSDate类用于保存时间值,同时提供了一些方法来处理一些基于秒级别时差(Time Interval)运算和日期之间的早晚比较等. 1. NSDate的构造方法和构造获取实例的属性 用于创建NSDat ...
- Ansible批量部署工具的安装
1.系统安装gcc,以及python2.6以上(2.6.8): 第一种比较简单的安装方法: 1)直接yum install -y ansible; 2)然后更改配置,/etc/ansible/ansi ...
- hdu 1528 Card Game Cheater (二分匹配)
Card Game Cheater Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- dashboard and reporting Interface analysis
dashboard and reporting Interface analysis > show system show system backup show system counters ...