//需要加一句手动扩栈
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#define maxn 50005
using namespace std;
bool vis[maxn];
int fa[maxn];
int dis[maxn];
int ans[maxn];
vector<int> G[maxn],w[maxn],Q[maxn],Num[maxn];
int n;
void init()
{
for(int i=1;i<=n;i++)
{
G[i].clear();
w[i].clear();
Num[i].clear();
Q[i].clear();
}
memset(dis,0,sizeof(dis));
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
fa[i]=i;
}
int Find(int x)
{
if(x!=fa[x]) return Find(fa[x]);
else return fa[x];
}
void Union(int x,int y)///注意合并的顺序,不是随便合并的
{
int tempa=Find(x);
int tempb=Find(y);
fa[tempb]=tempa;
}
void tarjan(int cur,int val)
{
vis[cur]=true;
dis[cur]=val;
for(int i=0;i<G[cur].size();i++)
{
int temp=G[cur][i];
if(vis[temp]) continue;
tarjan(temp,val+w[cur][i]); ///注意是先递归后合并
Union(cur,temp);
}
///即使query被重复访问也没关系,因为这一个不会被再合并
for(int i=0;i<Q[cur].size();i++)
{
int tmp=Q[cur][i];
if(!vis[tmp]) continue;
//cout<<Num[cur][i]<<" "<<cur<<" query "<<tmp<<endl;
/// cout<<cur<<" "<<Find(cur)<<" query "<<tmp<<" "<<Find(tmp)<<endl;
ans[Num[cur][i]]=dis[cur]+dis[tmp]-2*dis[Find(tmp)];
// cout<<Find(tmp)<<" "<<dis[Find(tmp)]<<" "<<ans[Num[cur][i]]<<endl;
}
}
int main()
{
int cas,q;
scanf("%d",&cas);
for(int ca=1;ca<=cas;ca++)
{
scanf("%d%d",&n,&q);
init();
int u,v,len,tempa,tempb;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&len);///反正push进的序号是一样的。。
G[u].push_back(v);
G[v].push_back(u);
w[u].push_back(len);
w[v].push_back(len);
}
for(int i=1;i<=q;i++)///加一个num vector 记录序号
{
scanf("%d%d",&tempa,&tempb);
Q[tempa].push_back(tempb);
Q[tempb].push_back(tempa);
Num[tempa].push_back(i);
Num[tempb].push_back(i);
}
tarjan(1,0);
for(int i=1;i<=q;i++)
cout<<ans[i]<<endl;
}
}
HDU 2586 LCA
最新推荐文章于 2020-08-26 10:34:35 发布