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.
题意:给出n个结点的树,q次询问,然后给出一条额外添加的边,从a到b距离为c。q次询问,给出u,v,询问uv的最短距离比原来短多少。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define N 100005
struct node
{
int u,v,w,next;
} e[2*N];
int head[N],dis[N],visit[N],pre[N],rrank[N],use[N];
int k;
void init()
{
k=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
e[k].u=u;
e[k].v=v;
e[k].w=w;
e[k].next=head[u];
head[u]=k++;
}
int fa[N][20],dep[N];
void dfs(int u)
{
use[u]=1;
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v=e[i].v;
if(!use[v])
{
dis[v]=dis[u]+e[i].w;
rrank[v]=rrank[u]+1;
pre[v]=u;
dfs(v);
}
}
}
/*倍增法求LCA nlogn*/
void bfs(int root)
{
queue<int>q;
dep[root]=0;
fa[root][0]=root;
q.push(root);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=1; i<20; i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v=e[i].v;
if(v==fa[u][0]) continue;
dep[v]=dep[u]+1;
fa[v][0]=u;
q.push(v);
}
}
}
int lca(int u,int v)
{
if(dep[u]>dep[v]) swap(u,v);
int hu=dep[u],hv=dep[v];
int tu=u,tv=v;
for(int det=hv-hu,i=0; det; det>>=1,i++)
{
if(det&1)
tv=fa[tv][i];
}
if(tv==tu) return tu;
for(int i=19; i>=0; i--)
{
if(fa[tu][i]==fa[tv][i]) continue;
tu=fa[tu][i];
tv=fa[tv][i];
}
return fa[tu][0];
}
int main()
{
int T,n,m,i,q,t=1;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
m=n-1;
init();
int u,v,w;
for(i=0; i<m; i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
memset(dis,0,sizeof(dis));
memset(pre,0,sizeof(pre));
memset(use,0,sizeof(use));
memset(rrank,0,sizeof(rrank));
memset(dep,0,sizeof(dep));
memset(fa,0,sizeof(fa));
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
dfs(b);//求dis
bfs(b);
printf("Case #%d:\n",t++);
while(q--)
{
scanf("%d%d",&u,&v);
int ua=dis[u]+dis[a]-2*dis[lca(u,a)];
int vb=dis[v];
int ub=dis[u];
int va=dis[v]+dis[a]-2*dis[lca(v,a)];
int uv=dis[u]+dis[v]-2*dis[lca(u,v)];
int ans=min(ua+vb,ub+va)+c;
printf("%d\n",max(0,uv-ans));
}
}
}