1. 程式人生 > >倍增lca--luogu3013貨車運輸

倍增lca--luogu3013貨車運輸

突發奇想寫部落格233

倍增lca。
先預處理出一個二維陣列,f[x][i]表示x節點的2^i的祖先是誰
在樹上dfs出各個點的深度順便求了f
在找lca的時候
先把兩個點調整到一個深度
如果調整完已經到同一個點上就退出
如果沒有就開始往上跳
從最大的開始跳
直到跳到相同的點
然後順便更新res的值
還有這道題要先求最長路建一顆樹··

粘程式碼

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 10000 #define mx 100000 using namespace std; int n,m,q,cnt,head[maxn],depth[maxn],f[maxn][32],fa[maxn]; int num,hd[maxn],root,w[maxn][32]; bool check[maxn]; struct node{ int to,nxt,w,frm; }edge[mx]; struct nd{ int to,nxt,w; }e[mx]; struct nnnn{ int p[maxn]; }nod[maxn]; bool cmp(node x,node y) { return
x.w>y.w; } int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } void add(int x,int y,int z) { cnt++; edge[cnt].to=y; edge[cnt].frm=x; edge[cnt].nxt=head[x]; edge[cnt].w=z; head[x]=cnt; } void buil(int x,int y,int z) { num++; e[num].to=y; e[num].nxt=hd[x]; e[num].w=z; hd[x]=num; } void
kruscal() { sort(edge+1,edge+cnt+1,cmp); int k=0; for(int i=1;i<=cnt;i++) { int u=edge[i].frm,v=edge[i].to; if(find(u)!=find(v)) { fa[find(v)]=find(u); buil(u,v,edge[i].w); buil(v,u,edge[i].w); k++; } if(k==n-1) break; } return ; } void dfs(int u,int father,int d) { check[u]=1; f[u][0]=father; depth[u]=d; for (register int i=hd[u];i;i=e[i].nxt) { int v=e[i].to; if (check[v]==0) { w[v][0]=e[i].w; dfs(v,u,d+1); } } } int bzlca(int x,int y) { int res=0x3f3f3f3f; if(depth[x]<depth[y]) swap(x,y); for(int i=20;i>=0;i--) { if(depth[f[x][i]]>=depth[y]) { res=min(res,w[x][i]); x=f[x][i]; } } if(x==y) { return res; } for(int i=20;i>=0;i--) { if(f[x][i]!=f[y][i]) { res=min(res,min(w[x][i],w[y][i])); x=f[x][i]; y=f[y][i]; } } res=min(res,min(w[x][0],w[y][0])); return res; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); } kruscal(); for(int i=1;i<=n;i++) { if(check[i]==0) { depth[i]=1; dfs(i,0,1); } } for(int j=1;j<=20;j++) for(int i=1;i<=n;i++) { f[i][j]=f[f[i][j-1]][j-1]; w[i][j]=min(w[i][j-1],w[f[i][j-1]][j-1]); } scanf("%d",&q); for(int i=1;i<=q;i++) { int a,b; scanf("%d%d",&a,&b); if(find(a)!=find(b)) printf("-1\n"); else printf("%d\n",bzlca(a,b)); } return 0; }