题目传送门

题意:先给一棵树,然后有一条额外的边,问u走到v从现在最短的路走和原来不加边走的路节省了多少距离

分析:首先跑不加边的树的LCA,这样能求出任意两点的距离,那么现在x和y多连了一条边,如果能节省路程那一定是走了xy这条边,那么暴力枚举组合,比如求u到v,新边xy,ans = min (ans, min (dux + dxy + dyv, duy + dyx + dxv))

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std; typedef long long ll;
const int N = 1e5 + 10;
const int D = 20;
const int INF = 0x3f3f3f3f;
struct Edge {
int v, w, nex;
Edge (int v = 0, int w = 0, int nex = 0) : v (v), w (w), nex (nex) {}
}edge[N<<1];
int head[N], dep[N], rt[D][N];
int d[N];
int n, q, e;
int x, y, cost; void init(void) {
memset (head, -1, sizeof (head));
e = 0;
} void add_edge(int u, int v, int w) {
edge[e] = Edge (v, w, head[u]);
head[u] = e++;
} void DFS(int u, int fa, int deep, int len) {
dep[u] = deep; d[u] = len; rt[0][u] = fa;
for (int i=head[u]; ~i; i=edge[i].nex) {
int v = edge[i].v, w = edge[i].w;
if (v == fa) continue;
DFS (v, u, deep + 1, len + w);
}
} int LCA(int u, int v) {
if (dep[u] < dep[v]) swap (u, v);
for (int i=0; i<D; ++i) {
if ((dep[u] - dep[v]) >> i & 1) {
u = rt[i][u];
}
}
if (u == v) return u;
for (int i=D-1; i>=0; --i) {
if (rt[i][u] != rt[i][v]) {
u = rt[i][u];
v = rt[i][v];
}
}
return rt[0][u];
} int solve(int u, int v) {
int lca = LCA (u, v);
int ans = d[u] + d[v] - d[lca] * 2; int lca1 = LCA (u, x);
int dux = d[u] + d[x] - d[lca1] * 2; int lca2 = LCA (u, y);
int duy = d[u] + d[y] - d[lca2] * 2; int lca3 = LCA (v, x);
int dvx = d[v] + d[x] - d[lca3] * 2; int lca4 = LCA (v, y);
int dvy = d[v] + d[y] - d[lca4] * 2; int mn = min (dux + dvy + cost, duy + dvx + cost);
if (mn > ans) return 0;
else return ans - mn;
} int main(void) {
int T, cas = 0; scanf ("%d", &T);
while (T--) {
init ();
scanf ("%d%d", &n, &q);
for (int u, v, w, i=1; i<n; ++i) {
scanf ("%d%d%d", &u, &v, &w);
add_edge (u, v, w);
add_edge (v, u, w);
}
scanf ("%d%d%d", &x, &y, &cost);
DFS (1, -1, 0, 0);
for (int i=1; i<D; ++i) {
for (int j=1; j<=n; ++j) {
rt[i][j] = rt[i-1][j] == -1 ? -1 : rt[i-1][rt[i-1][j]];
}
}
printf ("Case #%d:\n", ++cas);
for (int u, v, i=1; i<=q; ++i) {
scanf ("%d%d", &u, &v);
printf ("%d\n", solve (u, v));
}
} return 0;
}

  

LCA UESTC 92 Journey的更多相关文章

  1. cdoj 92 Journey tarjan/lca 树上点对距离

    Journey Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/92 Descri ...

  2. CDOJ 92 Journey(LCA&RMQ)

    题目连接:http://acm.uestc.edu.cn/#/problem/show/92 题意:给定一棵树,最后给加一条边,给定Q次查询,每次查询加上最后一条边之后是否比不加这条边要近,如果近的话 ...

  3. CDOJ 92 Journey LCA乱搞

    原题链接:http://acm.uestc.edu.cn/#/problem/show/92 题意: 给你一棵树,然后在树上连接一条边.现在有若干次询问,每次问你两个点(u,v)之间的距离在加那条边之 ...

  4. UESTC 1717 Journey(DFS+LCA)(Sichuan State Programming Contest 2012)

    Description Bob has traveled to byteland, he find the N cities in byteland formed a tree structure, ...

  5. CDOJ 92 – Journey 【LCA】

    [题意]给出一棵树,有n个点(2≤N≤105),每条边有权值,现在打算新修一条路径,给出新路径u的起点v,终点和权值,下面给出Q(1≤Q≤105)个询问(a,b)问如果都按照最短路径走,从a到b节省了 ...

  6. POJ 3278:The merchant(LCA&DP)

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6864   Accepted: 2375 Desc ...

  7. UESTC(LCA应用:求两点之间的距离)

    Journey Time Limit: 15000/3000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Bob has ...

  8. UESTC 912 树上的距离 --LCA+RMQ+树状数组

    1.易知,树上两点的距离dis[u][v] = D[u]+D[v]-2*D[lca(u,v)] (D为节点到根节点的距离) 2.某条边<u,v>权值一旦改变,将会影响所有以v为根的子树上的 ...

  9. POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)

    POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 [USACO]距离咨询(最近公共祖先) Description F ...

随机推荐

  1. Spring中的AOP(学习笔记)

    是什么AOP及实现方式 AOP的基本概念 Schema-base AOP Spring AOP API AspectJ

  2. redis中的五种基本的数据结构

    1 String 基本的数据类型. 2 list 2.1 将元素放入一个list中 rpush mylist A rpush mylist B rpush mylist A 如果mylist本来是不存 ...

  3. OO的片段,继承与组合,继承的优点与目的,虚机制在构造函数中不工作

    摘自C++编程思想: ------------------------------ 继承与组合:接口的重用 ------------------------------- 继承和组合都允许由已存在的类 ...

  4. 关于UISearchBar

    iPhone开发之UISearchBar学习是本文要学习的内容,主要介绍了UISearchBar的使用,不多说,我们先来看详细内容.关于UISearchBar的一些问题. 1.修改UISearchBa ...

  5. android adb 源码框架分析(2 角色)【转】

    本文转载自:http://blog.csdn.net/luansxx/article/details/25203323 角色 l  服务 服务是提供特定功能的实体,接收请求,返回应答是服务直接最表现. ...

  6. [RK3288][Android6.0] 调试笔记 --- pmu(rk818)寄存器读写【转】

    本文转载自:http://blog.csdn.net/kris_fei/article/details/76919134 Platform: Rockchip OS: Android 6.0 Kern ...

  7. 有关定时器setTimeout()、setInterval()详解

    JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成. setTimeout() setTimeout函数用 ...

  8. liunx操作系统安装<一>

    一:磁盘分区类型(1)主分区(最多四个主分区,比如window系统的C盘,D盘)(2)扩展分区,逻辑分区(为了能让磁盘多分出几个区域而存在)(3)交换分区(虚拟内存,当物理内存不足时候,作为应急存在)

  9. 利用记事本和cmd进行java编程(从安装IDE--编译--运行)

    java 最大特点---跨平台 所谓的跨平台性,是指软件可以不受计算机硬件和操作系统的约束而在任意计算机环境下正常运行.这是软件发展的趋势和编程人员追求的目标.之所以这样说,是因为计算机硬件的种类繁多 ...

  10. kubeadm安装Kubernetes13.1集群-三

    环境: master: 192.168.3.100 node01: 192.168.3.101 node02: 192.168.3.102 关闭所有主机防火墙,selinux: 配置主机互信: mas ...