T1 树上路径最小值
题目大意:
带点权的树 q次询问求每两个点之间路径上最小的点权
思路:
倍增lca裸题
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 100100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,q,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt; 21 int mn[MAXN][20],f[MAXN][20],val[MAXN],dep[MAXN]; 22 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 23 void dfs(int x) 24 { 25 for(int j=1;j<20&&(1<<j)<=dep[x];j++) 26 f[x][j]=f[f[x][j-1]][j-1],mn[x][j]=min(mn[x][j-1],mn[f[x][j-1]][j-1]); 27 for(int i=fst[x];i;i=nxt[i]) 28 if(!dep[to[i]]){dep[to[i]]=dep[x]+1,f[to[i]][0]=x,mn[to[i]][0]=min(mn[to[i]][0],val[x]);dfs(to[i]);} 29 } 30 int lca(int u,int v) 31 { 32 if(dep[u]<dep[v]) swap(u,v); 33 int t=dep[u]-dep[v],res=min(val[u],val[v]); 34 for(int i=0;i<20;i++) 35 if((1<<i)&t) res=min(res,mn[u][i]),u=f[u][i]; 36 if(u==v) return res; 37 for(int i=19;i>=0;i--) 38 if(f[u][i]!=f[v][i]) res=min(res,min(mn[u][i],mn[v][i])),u=f[u][i],v=f[v][i]; 39 return min(res,min(mn[u][0],mn[v][0])); 40 } 41 int main() 42 { 43 freopen("min.in","r",stdin); 44 freopen("min.out","w",stdout); 45 n=read(),q=read();int a,b; 46 for(int i=1;i<=n;i++) val[i]=mn[i][0]=read(); 47 for(int i=1;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);}dfs(1); 48 while(q--) 49 { 50 a=read(),b=read(); 51 printf("%d\n",lca(a,b)); 52 } 53 }