题意:给你一棵带权树,求某两点之间的距离,就是带权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++代码