Description

Bob has traveled to byteland, he find the N cities in byteland formed a tree structure, a tree structure is very special structure, there is exactly one path connecting each pair of nodes, and a tree with N nodes has N - 1 edges.

As a traveler, Bob wants to journey between those N cities, and he know the time each road will cost. he advises the king of byteland building a new road to save time, and then, a new road was built. Now Bob has Q journey plan, give you the start city and destination city, please tell Bob how many time is saved by add a road if he always choose the shortest path. Note that if it's better not journey from the new roads,
the answer is 0.

Input

First line of the input is a single integer T(1 <= T <= 20), indicating there are T test cases.

For each test case, the first will line contain two integers N(2 <= N <= 10^5) and Q(1 <= Q <= 10^5), indicating the number of cities in byteland and the journey plans. Then N line followed, each line will contain three integer x, y(1 <= x,y <= N) and z(1 <= z <= 1000) indicating there is a road cost z time connect the x-th city and the y-th city, the first N - 1 roads will form a tree structure, indicating the original roads, and the N-th line is the road built after Bob advised the king. Then Q line followed, each line will contain two integer x and y(1 <= x,y <= N), indicating there is a journey plan from the x-th city to y-th city.

Output

For each case, you should first output "Case #t:" in a single line, where t indicating the case number between 1 and T, then Q lines followed, the i-th line contains one integer indicating the time could saved in i-th journey plan.

题目大意:给一棵树T,每条边都有一个权值,然后又一条新增边,多次询问:从点x到点y在T上走的最短距离,在加上那条新增边之后,最短距离可以减少多少。

思路:任意确定一个根root,DFS计算每个点到根的距离dis[],然后每两点间的最短距离为dis[x]+dis[y]-2*dis[LCA(x,y)]。若新加入一条边u--v,那么如果我们必须经过u--v,那么从x到y的最短距离就为dis(x,u)+dis(u,v)+dis(v,y)或dis(x,v)+dis(v,u)+dis(u,y)。这样在线处理答案就行。

PS:至于求LCA的方法可以参考2007年郭华阳的论文《RMQ&LCA问题》,RMQ可以用ST算法,至于那个O(n)的±1RMQ有空再写把……

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAXN = ;
const int MAXM = MAXN * ; int head[MAXN];
int next[MAXM], to[MAXM], cost[MAXM];
int ecnt, root; void init() {
ecnt = ;
memset(head, , sizeof(head));
} void addEdge(int u, int v, int c) {
to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cost[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
} int dis[MAXN]; void dfs(int f, int u, int di) {
dis[u] = di;
for(int p = head[u]; p; p = next[p]) {
if(to[p] == f) continue;
dfs(u, to[p], di + cost[p]);
}
} int RMQ[*MAXN], mm[*MAXN], best[][*MAXN]; void initMM() {
mm[] = -;
for(int i = ; i <= MAXN * - ; ++i)
mm[i] = ((i&(i-)) == ) ? mm[i-] + : mm[i-];
} void initRMQ(int n) {
int i, j, a, b;
for(i = ; i <= n; ++i) best[][i] = i;
for(i = ; i <= mm[n]; ++i) {
for(j = ; j <= n + - ( << i); ++j) {
a = best[i - ][j];
b = best[i - ][j + ( << (i - ))];
if(RMQ[a] < RMQ[b]) best[i][j] = a;
else best[i][j] = b;
}
}
} int askRMQ(int a,int b) {
int t;
t = mm[b - a + ]; b -= ( << t)-;
a = best[t][a]; b = best[t][b];
return RMQ[a] < RMQ[b] ? a : b;
} int dfs_clock, num[*MAXN], pos[MAXN];//LCA void dfs_LCA(int f, int u, int dep) {
pos[u] = ++dfs_clock;
RMQ[dfs_clock] = dep; num[dfs_clock] = u;
for(int p = head[u]; p; p = next[p]) {
if(to[p] == f) continue;
dfs_LCA(u, to[p], dep + );
++dfs_clock;
RMQ[dfs_clock] = dep; num[dfs_clock] = u;
}
} int LCA(int u, int v) {
if(pos[u] > pos[v]) swap(u, v);
return num[askRMQ(pos[u], pos[v])];
} void initLCA(int n) {
dfs_clock = ;
dfs_LCA(, root, );
initRMQ(dfs_clock);
} int mindis(int x, int y) {
return dis[x] + dis[y] - * dis[LCA(x, y)];
} int main() {
int T, n, Q;
int x, y, z, p;
int u, v;
initMM();
scanf("%d", &T);
for(int t = ; t <= T; ++t) {
printf("Case #%d:\n", t);
scanf("%d%d", &n, &Q);
init();
for(int i = ; i < n - ; ++i) {
scanf("%d%d%d", &x, &y, &z);
addEdge(x, y, z);
}
scanf("%d%d%d", &x, &y, &z);
root = x;
dis[root] = ;
for(p = head[root]; p; p = next[p]) dfs(root, to[p], cost[p]);
initLCA(n);
while(Q--) {
scanf("%d%d", &u, &v);
int ans1 = mindis(u, v);
int ans2 = min(mindis(u, x) + mindis(y, v), mindis(u, y) + mindis(x, v)) + z;
if(ans1 > ans2) printf("%d\n", ans1 - ans2);
else printf("0\n");
}
}
}

  

UESTC 1717 Journey(DFS+LCA)(Sichuan State Programming Contest 2012)的更多相关文章

  1. 搜索分析(DFS、BFS、递归、记忆化搜索)

    搜索分析(DFS.BFS.递归.记忆化搜索) 1.线性查找 在数组a[]={0,1,2,3,4,5,6,7,8,9,10}中查找1这个元素. (1)普通搜索方法,一个循环从0到10搜索,这里略. (2 ...

  2. # 「银联初赛第一场」自学图论的码队弟弟(dfs找环+巧解n个二元一次方程)

    「银联初赛第一场」自学图论的码队弟弟(dfs找环+巧解n个二元一次方程) 题链 题意:n条边n个节点的连通图,边权为两个节点的权值之和,没有「自环」或「重边」,给出的图中有且只有一个包括奇数个结点的环 ...

  3. hdu----(2586)How far away ?(DFS/LCA/RMQ)

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  4. ZOJ 3781 Paint the Grid Reloaded(DFS连通块缩点+BFS求最短路)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5268 题目大意:字符一样并且相邻的即为连通.每次可翻转一个连通块X( ...

  5. hdu 3887 Counting Offspring(DFS序【非递归】+树状数组)

    题意: N个点形成一棵树.给出根结点P还有树结构的信息. 输出每个点的F[i].F[i]:以i为根的所有子结点中编号比i小的数的个数. 0<n<=10^5 思路: 方法一:直接DFS,进入 ...

  6. uva 10004 Bicoloring(dfs二分染色,和hdu 4751代码差不多)

    Description In the ``Four Color Map Theorem" was proven with the assistance of a computer. This ...

  7. CSU - 1356 Catch(dfs染色两种写法,和hdu4751比较)

    Description A thief is running away! We can consider the city to N–. The tricky thief starts his esc ...

  8. poj2718 Smallest Difference(dfs+特判,还可以贪心更快)

    https://vjudge.net/problem/POJ-2718 其实不太理解为什么10超时了.. 这题似乎是有贪心优化的方法的,我下面直接暴力了.. 暴力之余要特判两个点:1.超时点就是n=1 ...

  9. 线段树(dfs序建树加区间更新和单点查询)

    题目链接:https://cn.vjudge.net/contest/66989#problem/J 记录一下这道折磨了我一天的题,.... 具体思路: 具体关系可通过dfs序建树,但是注意,在更新以 ...

随机推荐

  1. Qt5应用程序封包

    系统环境:windows10+vs2017+qt5.12 目的:生成.exe可执行文件. 步骤: 1.选择release模式,生成解决方案. 2.打开命令行,cd到生成的可执行文件.exe目录下 3. ...

  2. MYSQL命令简要笔记

    mysqldump "C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqldump.exe"    --host=localhost ...

  3. Asp.Net Core使用Log4Net优化日志【项目开源】

    我在前一篇文章中介绍了一种使用Log4Net的方法,但是那种方法打出来的日志不是很直观 然后我前不久阅读了一篇非常不错的博客:https://www.cnblogs.com/guolianyu/p/9 ...

  4. day 25 模块与包

    一.模块   模块就是一个包含了python定义和申明的文件,文件名就是模块的名字加上.py的后缀/ 模块的分类:     1.使用python编写的py文件     2.已被编译位共享库或者DLL或 ...

  5. 使用docker搭建laravel记叙

    第一步,先从dockerhub上pull一个docker镜 docker pull laraedit/laraedit 这个docker镜像已经安装了 nginx.laravel和mysql,所以不需 ...

  6. Linux GPIO键盘驱动开发记录_OMAPL138

    Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...

  7. CRM2Stark组件

    CRM stark组件 开启新项目:CRM 再创建一个应用app02(python manage.py startapp app02 或者是工具栏:run...task:执行startapp app0 ...

  8. 《AngularJS学习整理》系列分享专栏

    <AngularJS学习整理>系列分享专栏   <AngularJS学习整理>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/re ...

  9. Scala学习笔记(三)—— 方法和函数

    1. 方法 方法使用 def 定义: def 方法名(参数名:参数列表,…) :返回值类型 = { 方法结构体 } scala> def add(x : Int ,y : Int):Int = ...

  10. LeetCode初级算法的Python实现--链表

    LeetCode初级算法的Python实现--链表 之前没有接触过Python编写的链表,所以这里记录一下思路.这里前面的代码是和leetcode中的一样,因为做题需要调用,所以下面会给出. 首先定义 ...