lca求最短距离(模板题)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define N 40005 using namespace std; int n,m;int num=0; int b[2*N],w[2*N],nt[2*N],p[2*N]; int fa[N][20],d[N],val[N]; void insert(){ num=0; scanf("%d%d",&n,&m); for(int i=1;i<=n-1;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); num++; b[num]=y; w[num]=z; nt[num]=p[x]; p[x]=num; num++; b[num]=x; w[num]=z; nt[num]=p[y]; p[y]=num; } } void dfs(int x,int h){ d[x]=h; for(int i=1;i<=20;i++){ if(d[x]<(1<<i))break; fa[x][i]=fa[fa[x][i-1]][i-1]; } for(int i=p[x];i;i=nt[i]){ int v=b[i]; if(v==fa[x][0]) continue; fa[v][0]=x; val[v]=val[x]+w[i]; dfs(v,h+1); } } int lca(int x,int y){ if(d[x]<d[y]) swap(x,y); int t=d[x]-d[y]; for(int i=0;i<=20;i++){ if(t&(1<<i)) x=fa[x][i]; } if(x==y) return x; for(int i=20;i>=0;i--){ if(fa[x][i]!=fa[y][i]) { x=fa[x][i];y=fa[y][i]; } } return fa[x][0]; } void solve(){ memset(fa,0,sizeof(fa)); memset(p,0,sizeof(p)); memset(val,0,sizeof(val)); insert(); dfs(1,0); while(m--){ int x,y; scanf("%d%d",&x,&y); int t=lca(x,y); printf("%d\n",val[x]+val[y]-2*val[t]); } } int main(){ int T; scanf("%d",&T); while(T--){ solve(); } return 0; }
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define M 500001 #define N 500001 using namespace std; int n,m,s;int num=0; int b[2*M],w[2*M],nt[2*M],p[N]; int fa[M][20],d[M]; void insert(){ scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=n-1;i++){ int x,y; scanf("%d%d",&x,&y); num++; b[num]=y; nt[num]=p[x]; p[x]=num; num++; b[num]=x; nt[num]=p[y]; p[y]=num; } } void dfs(int x){ for(int i=1;i<=20;i++){ if(d[x]<(1<<i)) break; fa[x][i]=fa[fa[x][i-1]][i-1]; } for(int i=p[x];i>0;i=nt[i]){ int v=b[i]; if(v==fa[x][0]) continue; fa[v][0]=x; d[v]=d[x]+1; dfs(v); } } int lca(int x,int y){ int h; if(d[x]<d[y]) swap(x,y); for(h=0;(1<<h)<=d[x];h++); h--; for(int i=h;i>=0;i--){ if(d[x]-(1<<i)>=d[y]) x=fa[x][i]; } /* 或者可以写成 int t=d[x]-d[y]; for(int i=0;i<=20;i++) { if(t&(1<<i)) x=fa[x][i]; } 利用位运算 20的解释同上 */ if(x==y) return x; for(int i=h;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } } return fa[x][0]; } int main(){ insert(); dfs(s); int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } return 0; }
P2912 [USACO08OCT]牧场散步Pasture Walking
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,q,cnt; int deep[1001],head[1001],dis[1001],fa[1001][11]; bool vis[1001]; struct data{int to,next,v;}e[2001]; void ins(int u,int v,int w) {e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;} void insert(int u,int v,int w) {ins(u,v,w);ins(v,u,w);} void dfs(int x) { vis[x]=1; for(int i=1;i<=9;i++) { if(deep[x]<(1<<i))break; fa[x][i]=fa[fa[x][i-1]][i-1]; } for(int i=head[x];i;i=e[i].next) { if(vis[e[i].to])continue; deep[e[i].to]=deep[x]+1; dis[e[i].to]=dis[x]+e[i].v; fa[e[i].to][0]=x; dfs(e[i].to); } } int lca(int x,int y) { if(deep[x]<deep[y])swap(x,y); int d=deep[x]-deep[y]; for(int i=0;i<=9;i++) if((1<<i)&d)x=fa[x][i]; for(int i=9;i>=0;i--) if(fa[x][i]!=fa[y][i]) {x=fa[x][i];y=fa[y][i];} if(x==y)return x; else return fa[x][0]; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); insert(u,v,w); } dfs(1); for(int i=1;i<=q;i++) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",dis[x]+dis[y]-2*dis[lca(x,y)]); } return 0; }