1. 程式人生 > 其它 >基於並查集的LCA最近公共祖先模板

基於並查集的LCA最近公共祖先模板

  把今天寫的LCA板子騰一下
1
#include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define maxn 40000 5 using namespace std; 6 7 struct EDGE 8 { 9 int nxt,to,v; 10 }edge[maxn*2+5]; 11 12 int T,n,root,cnt,m; 13 int head[maxn+5],dep[maxn+5],dis[maxn+5]; 14 int f[maxn+5
][25]; 15 bool vis[maxn+5]; 16 17 void add(int x,int y,int z) 18 { 19 edge[++cnt].to=y; 20 edge[cnt].v=z; 21 edge[cnt].nxt=head[x]; 22 head[x]=cnt; 23 } 24 25 void dfs(int u,int fa) 26 { 27 dep[u]=dep[fa]+1; 28 for(int i=0; i<=22; i++) 29 { 30 f[u][i+1
]=f[f[u][i]][i]; 31 } 32 for(int i=head[u]; i; i=edge[i].nxt) 33 { 34 if(edge[i].to==fa) 35 { 36 continue; 37 } 38 dis[edge[i].to]=dis[u]+edge[i].v; 39 f[edge[i].to][0]=u; 40 dfs(edge[i].to,u); 41 } 42 } 43 44 int
LCA(int x,int y) 45 { 46 if(dep[x]<dep[y]) 47 { 48 swap(x,y); 49 } 50 for(int i=22; i>=0; i--) 51 { 52 if(dep[f[x][i]]>=dep[y]) 53 { 54 x=f[x][i]; 55 } 56 if(x==y) 57 { 58 return x; 59 } 60 } 61 for(int i=22; i>=0; i--) 62 { 63 if(f[x][i]!=f[y][i]) 64 { 65 x=f[x][i]; 66 y=f[y][i]; 67 } 68 } 69 return f[x][0]; 70 } 71 72 int main() 73 { 74 scanf("%d",&T); 75 while(T--) 76 { 77 memset(vis,0,sizeof(vis)); 78 memset(edge,0,sizeof(edge)); 79 memset(f,0,sizeof(f)); 80 memset(dep,0,sizeof(dep)); 81 memset(head,0,sizeof(head)); 82 memset(dis,0,sizeof(dis)); 83 cnt=0; 84 scanf("%d%d",&n,&m); 85 for(int i=1; i<=n-1; i++) 86 { 87 int x,y,z; 88 scanf("%d%d%d",&x,&y,&z); 89 vis[y]=1; 90 add(x,y,z); 91 add(y,x,z); 92 } 93 for(int i=1; i<=n; i++) 94 { 95 if(vis[i]==0) 96 { 97 root=i; 98 break; 99 } 100 } 101 dfs(root,0); 102 for(int i=1; i<=m; i++) 103 { 104 int a,b; 105 scanf("%d%d",&a,&b); 106 printf("%d\n",dis[a]+dis[b]-2*dis[LCA(a,b)]); 107 } 108 } 109 return 0; 110 }

對於解決lca問題其實用強連通分量的Tarjan演算法是更高效的,當然也不能是一概而論