题意:问树上两点之间的最短距离
解题关键:LCA模板题,不知道为什么在hdu g++超时,c++70ms就过了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 typedef long long ll; 8 using namespace std; 9 const int maxn=40010; 10 const int maxm=25; 11 int _pow[maxm],m,n; 12 int head[maxn],tot; 13 int ver[maxn*2],depth[maxn*2],first[maxn],dis[maxn],rmq[maxn*2][maxm],id;//5个数组,注意哪个需要乘2 14 15 inline int read(){ 16 char k=0;char ls;ls=getchar();for(;ls<‘0‘||ls>‘9‘;k=ls,ls=getchar()); 17 int x=0;for(;ls>=‘0‘&&ls<=‘9‘;ls=getchar())x=(x<<3)+(x<<1)+ls-‘0‘; 18 if(k==‘-‘)x=0-x;return x; 19 } 20 21 struct edge{ 22 int to,w,nxt; 23 }e[maxn*2];//链式前向星建树 24 25 void init(){ 26 memset(head,-1,sizeof head); 27 tot=0; 28 id=0; 29 } 30 31 void add_edge(int u,int v,int w){ 32 e[tot].to=v; 33 e[tot].w=w; 34 e[tot].nxt=head[u]; 35 head[u]=tot++; 36 } 37 38 void dfs(int u,int fa,int dep){ 39 ver[++id]=u;//第i个访问到的结点编号 40 depth[id]=dep;//第i个访问到的结点深度 41 first[u]=id; 42 for(int i=head[u];i!=-1;i=e[i].nxt){ 43 int v=e[i].to; 44 int w=e[i].w; 45 if(v==fa) continue; 46 dis[v]=dis[u]+w;//dis是先序遍历求 47 dfs(v,u,dep+1); 48 ver[++id]=u;//后序遍历,再次访问父节点 49 depth[id]=dep; 50 } 51 } 52 53 void rmq_init(int n){ 54 int k=int(log(n)/log(2)); 55 for(int i=1;i<=n;i++) rmq[i][0]=i; 56 for(int j=1;j<=k;j++){ 57 for(int i=1;i+_pow[j]-1<=n;i++){//因为存的是索引 58 int a=rmq[i][j-1],b=rmq[i+_pow[j-1]][j-1]; 59 if(depth[a]<depth[b]) rmq[i][j]=a; 60 else rmq[i][j]=b; 61 } 62 } 63 } 64 65 int rmq_query(int l,int r){ 66 int k=int(log(r-l+1)/log(2)); 67 int a=rmq[l][k],b=rmq[r-_pow[k]+1][k]; 68 if(depth[a]<depth[b]) return a; 69 else return b; 70 }//返回的依然是索引 71 72 int LCA(int u,int v){ 73 int x=first[u],y=first[v]; 74 if(x>y)swap(x,y); 75 int res=rmq_query(x,y); 76 return ver[res]; 77 } 78 79 int main(){ 80 for(int i=0;i<maxn;i++) _pow[i]=1<<i; //预处理2^n 81 int t,a,b,c; 82 t=read(); 83 while(t--){ 84 init(); 85 n=read();m=read(); 86 for(int i=0;i<n-1;i++) a=read(),b=read(),c=read(),add_edge(a,b,c),add_edge(b,a,c); 87 dfs(1,-1,0); 88 rmq_init(2*n-1); 89 for(int i=0;i<m;i++){ 90 a=read(),b=read(); 91 int ans=LCA(a,b); 92 printf("%d\n",dis[a]+dis[b]-2*dis[ans]); 93 } 94 } 95 return 0; 96 }
时间: 2024-10-13 17:51:41