问题描述
村里有n栋房屋,还有一些双向道路连接起来。每天人们总是喜欢这样问:“如果我想从A房到B房,我能走多远?” 通常很难回答。但幸运的是,这个村庄的答案总是独一无二的,因为道路的建造方式是每两栋房屋之间有一条独特的简单路径(“简单”意味着你不能两次去一个地方)。Yout的任务是回答所有这些好奇的人。
输入
第一行是单个整数T(T <= 10),表示测试用例的数量。
对于每个测试用例,在第一行中有两个数字n(2 <= n <= 40000)和m(1 <= m <= 200),房屋数量和查询数量。下面的n-1行每个包含三个数字i,j,k,分隔在一个空格中,这意味着有一条连接房屋i和房屋j的道路,长度为k(0 <k <= 40000)。房屋是标记为1到n。
接下来m行每个都有不同的整数i和j,你可以回答房子i和房子j之间的距离。
产量
对于每个测试用例,输出m行。每行代表查询的答案。在每个测试用例后输出一条平淡的线。
样本输入
2
3 2
1 2 10
3 1 15
1 2
2 3
2 2
1 2 100
1 2
2 1
样本输出
10
25
100
100
dis[i]+dis[j]-2*dis[他们的公共祖先],就是要求的距离了
/*
*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <map>
#include <vector>
#include <set>
#include <bitset>
#include <stack>
#define ull unsigned long long
#define mems(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const double pi=acos(-1);
const int N=40004;
struct node
{
int u,v,w,next;
} g[N*2];
struct nod
{
int u,v,w,id,next;
} G[N*2];
int n,m,ans;
int head[N],hd[N];
int tot;
int res[N][4];
int dis[N];
int vis[N],pre[N],flag[N];
void init()
{
tot=0;
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
memset(flag,0,sizeof(flag));
memset(head,-1,sizeof(head));
memset(hd,-1,sizeof(hd));
memset(g,0,sizeof(g));
memset(G,0,sizeof(G));
}
void addg(int u,int v,int w)
{
g[tot].u=u;
g[tot].v=v;
g[tot].w=w;
g[tot].next=head[u];
head[u]=tot++;
}
void addG(int u,int v,int id)
{
G[tot].u=u;
G[tot].v=v;
// G[tot].w=w;
G[tot].id=id;
G[tot].next=hd[u];
hd[u]=tot++;
}
int Find(int x)
{
if(x==pre[x])
return x;
else
return pre[x]=Find(pre[x]);
}
void mix(int x,int y)
{
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
pre[fy]=fx;
}
void Tarjan(int u)
{
vis[u]=1;
for(int i=head[u]; ~i; i=g[i].next)
{
int v=g[i].v;//查找其儿子节点
if(!vis[v])//没有被访问过
{
dis[v]=dis[u]+g[i].w;//更新到根节点的距离
Tarjan(v);//从根节点继续查
mix(u,v);//把当前节点和它的父亲节点加入并查集
}
}
for(int i=hd[u]; ~i; i=G[i].next)
{
int v=G[i].v;//找到当前询问的点
if(vis[v])
{//如果当前的点被标记过,那么他们的最近公共祖先就是find(v),然后计算出路径
res[G[i].id][2]=Find(v);
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int a,b,c;
init();
for(int i=0; i<=n; i++)
{
pre[i]=i;
}
tot=0;
for(int i=1; i<n; i++)
{
scanf("%d%d%d",&a,&b,&c);
addg(a,b,c);
addg(b,a,c);
}
tot=0;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&a,&b);
addG(a,b,i);
addG(b,a,i);
res[i][0]=a;
res[i][1]=b;
}
Tarjan(1);
// Lca(1);
for(int i=1; i<=m; i++)
{
printf("%d\n",dis[res[i][0]]+dis[res[i][1]]-2*dis[res[i][2]]);
}
}
return 0;
}