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 }
View Code

相关文章:

  • 2021-07-06
  • 2021-12-28
  • 2021-12-15
  • 2021-06-15
  • 2021-04-02
  • 2021-08-12
  • 2021-12-25
  • 2021-05-27
猜你喜欢
  • 2021-10-23
  • 2022-03-05
  • 2021-08-19
  • 2022-12-23
  • 2021-07-10
  • 2021-04-18
相关资源
相似解决方案