题意:给你一棵带权树,求某两点之间的距离,就是带权LCA问题。
解题思路:我是把LCA转化为RMQ来做的,这题的确很水,直接把上次在poj上做的题目1986当模板就ko掉了模板的是还是不多说了。
注意输出格式。

#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
using namespace std;
typedef struct edge{
int w,to;
edge(int a,int b){to=a;w=b;}
}edge;
int n,m,sum[40005],deep,F[80005],B[80005],indx,pos[50005],M_min[80005][20];
bool cheack[40005],vs[40005];
vector<edge>g[40005];
void st()
{
int i,maxj,j,nexti;
for(i=0;i<indx;i++)
M_min[i][0]=i;
maxj=(int)(log(1.0*indx)/log(2.0));
for(j=1;j<=maxj;j++)
{
for(i=0;i+(1<<(j-1))<indx;i++)
{
nexti=i+(1<<(j-1));
if(B[M_min[i][j-1]]<=B[M_min[nexti][j-1]])
M_min[i][j]=M_min[i][j-1];
else
M_min[i][j]=M_min[nexti][j-1];
}
}
}
int Min_query(int x,int y,int &z)
{
int temp;
if(x>y)
{temp=x;x=y;y=temp;}
temp=(int)(log(1.0*(y-x+1))/log(2.0));
if(B[M_min[x][temp]]<=B[M_min[y-(1<<temp)+1][temp]])
{
z=M_min[x][temp];
return B[z];
}
else
{
z=M_min[y-(1<<temp)+1][temp];
return B[z];
}
}
void dfs_sum(int x)
{
B[indx]=deep;
F[indx++]=x;
vs[x]=true;
int i,v,w;
int wp=sum[x];
for(i=0;i<g[x].size();i++)
{
v=g[x][i].to;
w=g[x][i].w;
if(!vs[v])
{
sum[v]=w+wp;
deep++;
dfs_sum(v);
deep--;
B[indx]=deep;
F[indx++]=x;
}
}
}
int main()
{
int x,y,z,q,i,t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
for(i=0;i<=n;i++)
{
g[i].clear();
sum[i]=0;
vs[i]=cheack[i]=false;
pos[i]=-1;
}
for(i=0;i<n-1;i++)
{
scanf("%d %d %d",&x,&y,&z);
g[x].push_back(edge(y,z));
g[y].push_back(edge(x,z));
}
indx=deep=0;
dfs_sum(1);
for(i=0;i<indx;i++)
if(pos[F[i]]==-1)
pos[F[i]]=i;
/*  for(i=0;i<indx;i++)
{
printf("%d ",F[i]);
}
printf("\n");
for(i=0;i<indx;i++)
{
printf("%d ",B[i]);
}
printf("\n");
for(i=1;i<=n;i++)
{
printf("%d ",sum[i]);
}
printf("\n");
for(i=1;i<=n;i++)
printf("%d ",pos[i]);
printf("\n");*/
st();
for(i=0;i<m;i++)
{
scanf("%d %d",&x,&y);
Min_query(pos[x],pos[y],z);
printf("%d\n",sum[x]+sum[y]-2*sum[F[z]]);
}
if(t) printf("\n");
}
return 0;

93msG++代码