标签:
2 3 2 1 2 10 3 1 15 1 2 2 3 2 2 1 2 100 1 2 2 1
10 25 100 100
大致题意:求树上任意两点间的距离,显然就是u,v到根的距离减去他们的LCA到根的距离
由于刚学了LCA 用了三种LCA的方法求了
方法一:离线算法tarjan
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N = 40000+1000; int head[N]; int fst[N]; struct Edge { int v,w,nxt,id; }es[N<<1],qury[444]; int cnt,qc; int ans[222]; int fa[N],ance[N]; void inline add_query(int u,int v,int id) { qury[qc].v=v; qury[qc].id=id; qury[qc].nxt=fst[u]; fst[u]=qc++; qury[qc].v=u; qury[qc].id=id; qury[qc].nxt=fst[v]; fst[v]=qc++; } void inline add_edge(int u,int v,int w) { es[cnt].w=w; es[cnt].v=v; es[cnt].nxt=head[u]; head[u]=cnt++; es[cnt].v=u; es[cnt].w=w; es[cnt].nxt=head[v]; head[v]=cnt++; } int n,m; bool vis[N]; int getf(int x) { return x==fa[x]? x: fa[x]=getf(fa[x]); } void Merge(int u,int v) { fa[getf(u)]=getf(v); } void LCA(int u,int pa) { ance[u]=fa[u]=u; for(int i=head[u];~i;i=es[i].nxt) { int v=es[i].v; if(v==pa) continue; LCA(v,u); Merge(u,v); ance[getf(v)]=u; } vis[u]=1; for(int i=fst[u];~i;i=qury[i].nxt) { int v=qury[i].v; if(vis[v]) ans[qury[i].id]=ance[getf(v)]; } } int dp[N]; void makedp(int u,int pa) { for(int i=head[u];~i;i=es[i].nxt) { int v=es[i].v,w=es[i].w; if(v==pa) continue; dp[v]=dp[u]+w; makedp(v,u); } } void ini() { memset(head,-1,sizeof(head)); memset(fst,-1,sizeof(fst)); cnt=qc=0; memset(vis,0,sizeof(vis)); } int main() { int T; scanf("%d",&T); while(T--) { ini(); scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); } for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); add_query(u,v,i); } LCA(1,1); makedp(1,1); for(int i=0;i<m;i++) { int j=i<<1; printf("%d\n",dp[qury[j].v]+dp[qury[j^1].v]-2*dp[ans[i+1]]); } } return 0; }
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<algorithm> using namespace std; const int N = 40000+1000; int head[N]; struct Edge { int v,w,nxt; }es[N<<1]; int cnt; inline void add_edge(int u,int v,int w) { es[cnt].v=v; es[cnt].w=w; es[cnt].nxt=head[u]; head[u]=cnt++; es[cnt].v=u; es[cnt].w=w; es[cnt].nxt=head[v]; head[v]=cnt++; } int dp[N]; int dep[N]; bool vis[N]; int pa[N][20]; void bfs() { queue<int>q; q.push(1); pa[1][0]=1; vis[1]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=1;i<20;i++) pa[u][i]=pa[pa[u][i-1]][i-1]; for(int i=head[u];~i;i=es[i].nxt) { int v=es[i].v,w=es[i].w; if(vis[v]==0) { vis[v]=1; dp[v]=dp[u]+w; pa[v][0]=u; dep[v]=dep[u]+1; q.push(v); } } } } int LCA(int u,int v) { if(dep[u]>dep[v]) swap(u,v); for(int det=dep[v]-dep[u],i=0;det;i++,det>>=1) if(det&1) v=pa[v][i]; if(v==u) return v; for(int i=20-1;i>=0;i--) if(pa[u][i]!=pa[v][i]) v=pa[v][i],u=pa[u][i]; return pa[u][0]; } int n,m; void ini() { memset(head,-1,sizeof(head)); cnt=0; memset(vis,0,sizeof(vis)); dp[1]=0; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); ini(); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); } bfs(); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); int lcav = LCA(u,v); int ans = dp[u]+dp[v]-2*dp[lcav]; printf("%d\n",ans); } } return 0; }
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<algorithm> using namespace std; const int N = 40000+1000; int head[N]; struct Edge { int v,w,nxt; }es[N<<1]; int cnt; inline void add_edge(int u,int v,int w) { es[cnt].v=v; es[cnt].w=w; es[cnt].nxt=head[u]; head[u]=cnt++; es[cnt].v=u; es[cnt].w=w; es[cnt].nxt=head[v]; head[v]=cnt++; } int dp[N]; int index; int vs[N*3],id[N],dep[N]; int lca[N*3][20]; bool vis[N]; void dfs(int u,int h) { vis[u]=1; id[u]=++index; vs[index]=u; dep[u]=h; for(int i=head[u];~i;i=es[i].nxt) { int v=es[i].v,w=es[i].w; if(vis[v]) continue; dp[v]=dp[u]+w; dfs(v,h+1); vs[++index]=u; } } int mm[N]; void ini() { memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head)); cnt=index=0; dp[1]=0; } int n,m; int main() { mm[0]=-1; for(int i=1;i<=N-1;i++)mm[i]= (((i-1)&i)==0)? mm[i-1]+1:mm[i-1]; int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); ini(); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); } dfs(1,0); for(int i=1;i<=index;i++) lca[i][0]=vs[i]; for(int j=1;j<20;j++) for(int i=1;i+(1<<j)-1<=index;i++) { int a=lca[i][j-1],b=lca[i+(1<<(j-1))][j-1]; lca[i][j] = dep[a]<dep[b] ? a:b; } for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); int l=min(id[u],id[v]); int r=max(id[u],id[v]); int k=mm[r-l+1]; int a=lca[l][k],b=lca[r-(1<<k)+1][k]; int lcav = dep[a]<dep[b]? a:b; int ans = dp[u]+dp[v]-2*dp[lcav]; printf("%d\n",ans); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 2586 How far away ? (初学LCA)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/46793621