HDU 2586——How far away ?
| Time limit | 1000 ms |
| Memory limit | 32768 kB |
Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
Input
First line is a single integer T(T<=10), indicating the number of test cases.
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.
Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
Sample Input
2
3 2
1 2 10
3 1 15
1 2
2 3 2 2
1 2 100
1 2
2 1
Sample Output
10
25
100
100
题目分析
乍一看,这个是求最短路的问题,本想着prim算法弄完,但是奈何这个题目被归在了RMQ&LCA专题里面,而且这个结点的个数最大有4w个,为了防止用prim算法出现超时,最后还是老老实实的去学了LCA算法,我推荐一个学这个东西的地方,讲的还不错,有这个题目的原题讲解 https://www.bilibili.com/video/av41067872/?p=5
好了,来分析一下这个题目吧,求指定村庄之间的最短距离,因为要用到 Lowest Common Ancestor 算法,我们用dis[x]表示结点(也就是城市x)离根结点的距离,由于题目的特殊性, "But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses" , 这个地方说明了每两个城市之间的路是固定的,有且只有一条(想到这里,发现哪里是什么最短路,就是要你求两点之间的距离)。
假设u,v为要求距离的两个城市,k表示二者的LCA,那么dis[u] - dis[k] 为u距离LCA的距离,而dis[v] - dis[k] 为v距离LCA的距离,所以dis[u] + dis[v] - 2 * dis[k] 就是两个城市之间的距离,然后其他的步骤就按照LCA算法求出LCA就好,LCA的教程请参考上面的哪个网址,个人觉得讲的很好。
代码区
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include <vector>
using namespace std;
const int inf = 0x3f3f3f3f;
const int max2 = 100 + 10;
const int max3 = 1000 + 10;
const int max4 = 10000 + 10;
typedef struct Edge{
int to;
int val;
Edge(int to = 0 , int val = 0):to(to),val(val){}
}Edge;
vector<Edge>road[4 * max4]; //road[x]保存从x出发的所有道路,road[x][i].to表示这条路的另一个点
int dis[4 * max4]; //dis[x]记录结点x离根结点的距离
int father[4 * max4][15]; //father[x][j]记录从x点向上2^j次层的祖先结点
int depth[4 * max4]; //depth[x]记录点x的深度
int lg[4 * max4]; //log2n 向下取整
void init()
{
memset(dis, 0, sizeof(dis));
memset(father, 0, sizeof(father));
memset(depth, 0, sizeof(depth));
for (int i = 0; i < 4 * max4;i++)
road[i].clear();
}
void dfs(int now,int fa)
{
depth[now] = depth[fa] + 1;
father[now][0] = fa;
//将now点的祖先结点全部记录下来
for (int j = 1; j <= lg[depth[now]] + 1; j++)
father[now][j] = father[father[now][j - 1]][j - 1];
//搜索当前结点的子结点
for (int i = 0; i < road[now].size();i++)
{
if(road[now][i].to != fa) //如果某一条路是当前结点和父结点的,那么没有必要向上搜索
{
dis[road[now][i].to] = dis[now] + road[now][i].val; //子结点到根结点的距离等于父结点到根结点的距离加上这条路的距离
dfs(road[now][i].to, now);
}
}
}
//返回结点u,v的最小公共祖先
int lca(int u,int v)
{
if (depth[u] < depth[v])
swap(u, v);
while (depth[u] != depth[v])
u = father[u][lg[depth[u] - depth[v]]];
if (u == v)
return u;
for (int i = lg[depth[u]];i >= 0;i--)
{
//当两者的某祖先结点不一致的时候,说明还需要继续向上查找
//当u,v位lca的最近子结点的时候,对于任意的father[u][i]都满足
//father[u][i] == father[v][i] ,所以最后u,v为lca的最近子结点
if(father[u][i] != father[v][i])
{
u = father[u][i];
v = father[v][i];
}
}
return father[u][0];
}
int main()
{
//预处理,lg[x]表示log2n向下取整
lg[0] = -1;
for (int i = 1; i < 4 * max4;i++)
lg[i] = lg[i >> 1] + 1;
int t;
scanf("%d",&t);
while(t--)
{
init();
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i < n; i++)
{
int s, e, v;
scanf("%d%d%d", &s, &e, &v);
road[s].push_back({ e,v });
road[e].push_back({ s,v });
}
dfs(1, 0); //树中任意一个结点均可以作为根结点,但是不确定结点的个数,而且编号为1的结点所以的树均有,所以将1作为根结点
while(m--)
{
int s, e;
scanf("%d%d", &s, &e);
int k = lca(s, e);
printf("%d\n", dis[s] + dis[e] - 2 * dis[k]);
}
}
return 0;
}
HDU 2586——How far away ?的更多相关文章
- HDU - 2586 How far away ?(LCA模板题)
HDU - 2586 How far away ? Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & ...
- hdu 2586 How far away ?倍增LCA
hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...
- HDU 2586 How far away ?【LCA】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Oth ...
- HDU 2586.How far away ?-离线LCA(Tarjan)
2586.How far away ? 这个题以前写过在线LCA(ST)的,HDU2586.How far away ?-在线LCA(ST) 现在贴一个离线Tarjan版的 代码: //A-HDU25 ...
- HDU 2586 How far away ? (LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 LCA模版题. RMQ+LCA: #include <iostream> #incl ...
- hdu - 2586 How far away ?(最短路共同祖先问题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 最近公共祖先问题~~LAC离散算法 题目大意:一个村子里有n个房子,这n个房子用n-1条路连接起 ...
- HDU 2586 How far away ?(LCA在线算法实现)
http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的 ...
- HDU 2586 How far away ?(LCA模板 近期公共祖先啊)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...
- HDU 2586 How far away ?【LCA模板题】
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给你N个点,M次询问.1~N-1行输入点与点之间的权值,之后M行输入两个点(a,b)之间的最 ...
- hdu 2586 How far away ?(LCA - Tarjan算法 离线 模板题)
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
随机推荐
- java文件上传下载解决方案
javaweb上传文件 上传文件的jsp中的部分 上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求 1.通过form表单向后端发送请求 <form id=" ...
- C语言 - strcmp和strncmp的编程实现及总结
一.strcmp和strncmp的编程实现及总结 1.strcmp函数的实现 要求: 原型: int strcmp(char *dest,char * src,int n); 头文件:# ...
- 文件操作:fopen()
r 打开只读文件,该文件必须存在. r+ 打开可读写的文件,该文件必须存在. rb+ 读写打开一个二进制文件,只允许读写数据. rt+ 读写打开一个文本文件,允许读和写. w 打开只写文件, ...
- 如何在IntelliJ Idea中同时启动不同端口
配置多实例: 选择Idea右上角启动按钮边上的Edit Configurations,在打开的对话框中,去掉Single Instance Only的选项,VM Options中增加-Dserver. ...
- JIRA7.13版本创建项目:字段和界面(三)
这是我从网上找的资料和最新版的相差不大,可以借鉴原文链接:http://ju.outofmemory.cn/entry/367224 项目的版本号取决于修复版本,不是影响版本 字段 我们已经知道如何在 ...
- sqli-labs(43)
0X01和42关比起来 只是闭合变了 那么我们可以构造 ');insert into users values(98,'zhong','zhong')# 成功注入
- 【每日一包0009】group-array
[github地址:https://github.com/ABCDdouyae...] group-array 对数组里面的多项按照指定的key进行整合 用法:group-array(arr, key ...
- LeetCode 24. 两两交换链表中的节点(Swap Nodes in Pairs)
题目描述 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 说明: 你的算法只能 ...
- laravel 使用不同账号发送邮件的问题
业务背景: 公司自己做的oa系统,不同的模块需要用不同的邮箱发送信息给收件人.比如:员工离职的时候用离职的邮箱发送离职邮件通知,员工入职的时候用入职的邮箱发送入职邮件通知.发邮件是一件耗时的任务,如果 ...
- App架构设计:接口的设计
安全机制的设计 现在,大部分App的接口都采用RESTful架构,RESTFul最重要的一个设计原则就是,客户端与服务器的交互在请求之间是无状态的,也就是说,当涉及到用户状态时,每次请求都要带上身份验 ...