The traffic network in a country consists of N cities (labeled with integers from 1 to N) and N-1 roads connecting

the cities. There is a unique path between each pair of different cities, and we know the exact length of each road.

Write a program that will, for each of the K given pairs of cities, find the length of the shortest and the length

of the longest road on the path between the two cities.

Input

The first line of input contains an integer N, 2 ≤ N ≤ 100 000. Each of the following N-1 lines contains three

integers A, B and C meaning that there is a road of length C between city A and city B. 
The length of each road will be a positive integer less than or equal to 1 000 000. 
The next line contains an integer K, 1 ≤ K ≤ 100 000. Each of the following K lines contains two different

integers D and E – the labels of the two cities constituting one query.

Output

Each of the K lines of output should contain two integers – the lengths from the task description for the

corresponding pair of the cities.

题目大意:给一棵n个点的树,每条边有一个权值,k个询问,问u到v的简单路径中,权值最小和最大分别为多少。

思路:首先要会普通的tarjan求LCA的算法,在合并集合的时候算出每个点到其根节点的最小和最大权值,在求出某一对询问(u, v)的LCA之后,回溯到他们的LCA的时候把LCA的子集都合并到了LCA上,那么u和v分别到LCA的最小最大权值就知道了,再取其中的最小最大值即可。

PS:时间复杂度为O(n+k)

代码(6470MS):

 #include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define X first
#define Y second
typedef pair<int, int> PII;
typedef vector<PII> VPII;
typedef vector<int> VI; const int MAXN = ;
const int MAXE = MAXN << ;
const int INF = 0x7fff7fff; int head[MAXN], to[MAXE], next[MAXE], cost[MAXE], ecnt;
int n, m, fa[MAXN]; PII edge[MAXN], a[MAXN], ans[MAXN];
VPII query[MAXN];
VI b[MAXN]; bool vis[MAXN]; void init() {
for(int i = ; i <= n; ++i) fa[i] = i;
ecnt = ;
} void add_edge(int u, int v, int w) {
to[ecnt] = v; cost[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cost[ecnt] = w; next[ecnt] = head[v]; head[v] = ecnt++;
} int get_set(int x) {
if(fa[x] == x) return x;
int ret = get_set(fa[x]);
edge[x].X = max(edge[x].X, edge[fa[x]].X);
edge[x].Y = min(edge[x].Y, edge[fa[x]].Y);
return fa[x] = ret;
} void LCA(int u, int f) {
edge[u].X = ; edge[u].Y = INF;
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(v == f) continue;
LCA(v, u);
edge[v].X = edge[v].Y = cost[p];
fa[v] = u;
}
vis[u] = true;
for(VPII::iterator it = query[u].begin(); it != query[u].end(); ++it)
if(vis[it->X]) b[get_set(it->X)].push_back(it->Y);
for(VI::iterator it = b[u].begin(); it != b[u].end(); ++it) {
int id = *it, u = a[id].X, v = a[id].Y;
get_set(u); get_set(v);
ans[id] = make_pair(max(edge[u].X, edge[v].X), min(edge[u].Y, edge[v].Y));
}
} int main() {
scanf("%d", &n);
init();
for(int i = ; i < n; ++i) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
scanf("%d", &m);
for(int i = ; i <= m; ++i) {
scanf("%d%d", &a[i].X, &a[i].Y);
query[a[i].X].push_back(make_pair(a[i].Y, i));
query[a[i].Y].push_back(make_pair(a[i].X, i));
}
LCA(, );
for(int i = ; i <= m; ++i) printf("%d %d\n", ans[i].Y, ans[i].X);
}

最新文章

  1. java文档注释--javadoc的用法
  2. Mac环境下Octopress个人博客搭建
  3. 导入导出Excel工具类ExcelUtil
  4. poj 1112
  5. DataView usage combind with event and ViewModel From ERP-DEV
  6. Asp.net MVC 4 Html帮助类
  7. 忽然发现,if语句没有相应的continue功能
  8. jQuery插件的编写相关技术 设计总结和最佳实践
  9. 19. leetcode 100. Same Tree
  10. BigDecimal精确计算及陷阱
  11. RoportNG报表显示中文乱码和TestNG显示中文乱码实力解决办法
  12. Jmeter学习系列----2 录制脚本
  13. echarts常用方法,legend状态支持两张图片切换(四)
  14. SpringBoot 启动概述
  15. 终止java线程的2种方法
  16. Pandas 基础(4) - 读/写 Excel 和 CSV 文件
  17. python实现定时任务
  18. 栈的理解和代码实现(java)
  19. java泛型通配符?
  20. [Training Video - 7] [Database connection] Various databases which are supported, Drivers for database connection, SQL Groovy API

热门文章

  1. 【转】RMAN删除过期备份或非过期备份
  2. 概括iOS知识点思维导图
  3. web常用软件
  4. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛--I-填空题
  5. 《linux设备驱动开发详解》笔记——15 linux i2c驱动
  6. Python学习:for 循环 与 range()函数
  7. 「LibreOJ#516」DP 一般看规律
  8. COURSES POJ1469(模板)
  9. JAVA多进程入门
  10. 8 TFTP代码详解 协议写在程序中