什么是欧拉序,可以去这个大佬的博客(https://www.cnblogs.com/stxy-ferryman/p/7741970.html)巨详细
因为欧拉序中的两点之间,就是两点遍历的过程,所以只要找遍历过程中对应的最小的深度就行了,这里用st表存,first存第一个u出现的地方,用value存欧拉序,同时用depth存对应深度
模板
struct node{ int v,next,dist; }a[maxn<<1]; int n,m,tot,len; int st[maxn<<1][20], depth[maxn<<1],value[maxn<<1],first[maxn<<1]; int dist[maxn],head[maxn]; void add(int u,int v,int dist0){ a[tot].next=head[u]; a[tot].dist=dist0; a[tot].v=v; head[u]=tot++; } void dfs(int u,int fa,int d) { value[++len]=u;depth[len]=d;first[u]=len; for (int i=head[u];~i;i=a[i].next){ int v=a[i].v;if(v==fa)continue; dist[v]=dist[u]+a[i].dist; dfs(v,u,d+1); value[++len]=u;depth[len]=d; } } inline void init(int n){ for(int i=0;i<=n;i++)head[i]=-1,depth[i]=0; tot=0,len=0; } inline void makest(){ for(it i=1;i<=len;i++)st[i][0]=depth[i]; for(it i=1;1<<i<=len;i++){ for(it j=1;j+(1<<i)-1<=len;j++){ st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]); } } } inline int dis(int u,int v){ int l=first[u],r=first[v]; if(l>r){swap(l,r);} int k=log2(r-l+1); int dep=min(st[l][k],st[r-(1<<k)+1][k]); return dist[u]+dist[v]-2*dist[value[first[dep]]]; }
题意:
以1为根的树,两个点之间的最近距离是多少
思路:
模板LCA
#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline #define it register int #define inf 0x3f3f3f3f #define lowbit(x) (x)&(-x) #define mem(a,b) memset(a,b,sizeof(a)) #define modd 998244353 const int maxn=4e4+10; struct node{ int v,next,dist; }a[maxn<<1]; int n,m,tot,len; int st[maxn<<1][20], depth[maxn<<1],value[maxn<<1],first[maxn<<1]; int dist[maxn],head[maxn]; void add(int u,int v,int dist0){ a[tot].next=head[u]; a[tot].dist=dist0; a[tot].v=v; head[u]=tot++; } void dfs(int u,int fa,int d) { value[++len]=u;depth[len]=d;first[u]=len; for (int i=head[u];~i;i=a[i].next){ int v=a[i].v;if(v==fa)continue; dist[v]=dist[u]+a[i].dist; dfs(v,u,d+1); value[++len]=u;depth[len]=d; } } inline void init(int n){ for(int i=0;i<=n;i++)head[i]=-1,depth[i]=0; tot=0,len=0; } inline void makest(){ for(it i=1;i<=len;i++)st[i][0]=depth[i]; for(it i=1;1<<i<=len;i++){ for(it j=1;j+(1<<i)-1<=len;j++){ st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]); } } } inline int dis(int u,int v){ int l=first[u],r=first[v]; if(l>r){swap(l,r);} int k=log2(r-l+1); int dep=min(st[l][k],st[r-(1<<k)+1][k]); return dist[u]+dist[v]-2*dist[value[first[dep]]]; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); init(n); for(it i=0;i<n-1;i++){int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w);add(v,u,w); } dfs(1,0,1); makest(); while(m--){ int l,r; scanf("%d%d",&l,&r); printf("%d ",dis(l,r)); } } return 0; }
#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline #define it register int #define inf 0x3f3f3f3f #define lowbit(x) (x)&(-x) #define mem(a,b) memset(a,b,sizeof(a)) #define modd 998244353 const int maxn=4e4+10; struct node{ int v,next,dist; }a[maxn<<1]; int n,m,tot; int fath[maxn][20], depth[maxn]; int dist[maxn],head[maxn]; void add(int u,int v,int dist0){ a[tot].next=head[u]; a[tot].dist=dist0; a[tot].v=v; head[u]=tot++; } void dfs(int u,int fa,int d) { fath[u][0]=fa; depth[u]=d; for(int i=1;i<20;i++) fath[u][i]=fath[fath[u][i-1]][i-1]; for (int i=head[u];~i;i=a[i].next){ int v=a[i].v;if(v==fa)continue; dist[v]=dist[u]+a[i].dist; dfs(v,u,d+1); } } void init(int n){ for(int i=0;i<=n;i++)fath[i][0]=0,dist[i]=0,head[i]=-1,depth[i]=0; tot=0; } inline int lca(int x,int y){ if(depth[x]<depth[y])swap(x,y); int h=depth[x]-depth[y]; for(it i=0;h>0;i++){ if(h&1){ x=fath[x][i]; } h>>=1; } if(x==y)return x; for(it i=19;i>=0;i--){ if(fath[x][i]!=fath[y][i]){ x=fath[x][i]; y=fath[y][i]; } } return fath[x][0]; } inline int dis(int u,int v){ int d=lca(u,v); return dist[u]+dist[v]-2*dist[d]; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); init(n); for(it i=0;i<n-1;i++){int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w);add(v,u,w); } dfs(1,0,1); while(m--){ int l,r; scanf("%d%d",&l,&r); printf("%d ",dis(l,r)); } } return 0; }