原题链接:http://acm.uestc.edu.cn/#/problem/show/92

题意:

给你一棵树,然后在树上连接一条边。现在有若干次询问,每次问你两个点(u,v)之间的距离在加那条边之后减小了多少。

题解:

对于那条加入的边,只有两种情况,要么走,要么不走。不走的距离就是$dis[u]+dis[v]-2*dis[LCA(u,v)]$,其中$dis$表示点到根节点的距离,LCA表示最近公共祖先。现在考虑走的情况:设加入的那条边是$(a,b)$,边权是c,那么答案显然是:

$$min(DIS(a,u)+DIS(b,v)+c,DIS(a,v)+DIS(b,u)+c)$$

其中DIS表示两点间在树上的最短距离。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define MAX_N 100005
#define MAX_D 22
using namespace std; struct edge {
public:
int to, cost; edge(int t, int c) : to(t), cost(c) { } edge() { }
}; vector<edge> G[MAX_N]; int n,q; int ancestor[MAX_N][MAX_D];
int depth[MAX_N]; int dis[MAX_N]; void init(){
memset(dis,,sizeof(dis));
memset(ancestor,,sizeof(ancestor));
memset(depth,,sizeof(depth));
for(int i=;i<=n;i++)G[i].clear();
} void dfs(int u,int p) {
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i].to;
if (v == p)continue;
dis[v]=dis[u]+G[u][i].cost;
depth[v] = depth[u] + ;
ancestor[v][] = u;
dfs(v, u);
}
} void getAncestor() {
for (int j = ; j < MAX_D; j++)
for (int i = ; i <= n; i++)
ancestor[i][j] = ancestor[ancestor[i][j - ]][j - ];
} int LCA(int u,int v) {
if (depth[u] < depth[v])swap(u, v);
for (int i = MAX_D - ; i >= ; i--) {
if (depth[ancestor[u][i]] >= depth[v]) {
u = ancestor[u][i];
if (depth[u] == depth[v])break;
}
}
if (u == v)return u;
for (int i = MAX_D - ; i >= ; i--) {
if (ancestor[u][i] != ancestor[v][i]) {
u = ancestor[u][i];
v = ancestor[v][i];
}
}
return ancestor[u][];
} int getDis(int u,int v) {
int L = LCA(u, v);
return dis[u] + dis[v] - * dis[L];
} int T;
int cas=; int main() {
cin >> T;
while (T--) {
printf("Case #%d:\n", ++cas);
scanf("%d%d", &n, &q);
init();
for (int i = ; i < n - ; i++) {
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
G[u].push_back(edge(v, c));
G[v].push_back(edge(u, c));
}
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
dfs(, );
getAncestor();
while (q--) {
int u, v;
scanf("%d%d", &u, &v);
int tmp, ans;
ans = tmp = getDis(u, v);
ans = min(ans, getDis(u, x) + getDis(y, v) + z);
ans = min(ans, getDis(u, y) + getDis(x, v) + z);
printf("%d\n", tmp - ans);
}
}
return ;
}

最新文章

  1. zsh 自动补全导致命令显示重复
  2. ABP框架理论学习之Debugging
  3. centos7 没有iptables服务 file or directory? 用secureCRT登录centos?
  4. Android 4.4以上的存储读写权限
  5. zabbix监控交换机
  6. jquery选择器(原创)&lt;三&gt;
  7. Objective-C的可变是如何实现的?
  8. 狗狗40题~(Volume B)
  9. 2014第11周一word样式
  10. 【翻译】我钟爱的Visual Studio前端开发工具/扩展
  11. ROS学习记录(三)————创建一个简单的发布节点和订阅节点
  12. jQuery检查复选框是否被选
  13. AT3611 Tree MST
  14. 为什么需要注册OCX控件?
  15. Windows平台下tomcat 性能调优
  16. LeetCode OJ 19. Remove Nth Node From End of List
  17. ArcGIS案例学习笔记-查找重叠的多边形
  18. First Day!
  19. 说说http协议中的编码和解码
  20. android 获取经纬度

热门文章

  1. Python中的列表(1)
  2. Python头脑风暴3
  3. SmartGit 30天评估期结束解决办法
  4. (转)减少oracle sql回表次数 提高SQL查询性能
  5. 【转】git bash here 右键菜单失效后的修复方法
  6. luogu1208 尼克的任务
  7. 为Anaconda添加新的源
  8. 读《MySql必知必会》笔记
  9. hibernate与struts框架实现增删改查
  10. 【bzoj】P4407于神之怒加强版(莫比乌斯反演)