最近公共祖先--lca

Posted wzq--boke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近公共祖先--lca相关的知识,希望对你有一定的参考价值。

 

模版题

https://www.luogu.org/problemnew/show/P3379

技术分享图片
 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<queue>
 8 #define ll long long
 9 using namespace std;
10 
11 inline ll read(){
12     ll x=0,f=1; char ch=getchar();
13     for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
14     for(;isdigit(ch);ch=getchar())x=ch-0+(x<<3)+(x<<1);
15     return x*f;
16 }
17 
18 const int maxn=510000+1010;
19 int n,q,a[maxn],head[maxn],nx[maxn<<1],to[maxn<<1],tot;
20 
21 inline void add(int x,int y){
22     to[++tot]=y;nx[tot]=head[x];head[x]=tot;
23     to[++tot]=x;nx[tot]=head[y];head[y]=tot;    
24 }
25 
26 int dep[maxn],dp[maxn][21],f[maxn][21];
27 void Deal(int u,int fa){
28     dep[u]=dep[fa]+1;
29     for(int i=1;i<=20;i++){
30         f[u][i]=f[f[u][i-1]][i-1];
31         dp[u][i]=min(dp[u][i-1],dp[f[u][i-1]][i-1]);
32     }
33     for(int i=head[u];i;i=nx[i]){
34         int k=to[i];
35         if(k==fa)continue;
36         f[k][0]=u;
37         dp[k][0]=min(a[k],a[u]);
38         Deal(k,u);    
39     }
40 }
41 
42 int lca(int x,int y){
43     int minn=min(a[x],a[y]);
44     if(dep[x]<dep[y])swap(x,y);
45     for(int i=20;i>=0;i--){
46         if(dep[f[x][i]]>=dep[y]){
47             minn=min(dp[x][i],minn);
48             x=f[x][i];
49         }
50         if(x==y)return x;
51     }
52     for(int i=20;i>=0;i--){
53         if(f[x][i]!=f[y][i]){
54             minn=min(minn,min(dp[x][i],dp[y][i]));
55             x=f[x][i];
56             y=f[y][i];
57         }
58     }
59     return f[x][0];
60 }
61 
62 int s;
63 int main(){
64     n=read();q=read();
65     s=read();
66     memset(dp,127,sizeof(dp));
67     for(int i=1;i<n;i++){
68         add(read(),read());
69     }
70     Deal(s,0);
71     for(int i=1;i<=q;i++){
72         printf("%d
",lca(read(),read()));
73     }
74     return 0;
75 }
View Code

 

严格次小生成树

https://www.luogu.org/problemnew/show/P4180

技术分享图片
  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<queue>
  8 #define ll long long
  9 using namespace std;
 10 
 11 inline ll read(){
 12     ll x=0,f=1; char ch=getchar();
 13     for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
 14     for(;isdigit(ch);ch=getchar())x=ch-0+(x<<3)+(x<<1);
 15     return x*f;
 16 }
 17 
 18 inline void write(ll n){
 19     char ch[24]; int top=0;
 20     if(n==0){putchar(0);return ;}
 21     if(n<0)putchar(-),n=-n;
 22     while(n)ch[++top]=n%10+0,n/=10;
 23     while(top)putchar(ch[top--]);
 24     return ;
 25 }
 26 
 27 const int maxn=300000+1010;
 28 const ll inf=21474836460000ll;
 29 
 30 int n,m,tot,head[maxn],f[maxn];
 31 ll num;
 32 bool book[maxn];
 33 
 34 struct wzq{int x,y,z;}a[maxn];
 35 struct hhh{int to,nx,v;}b[maxn<<1];
 36 
 37 inline void add(int x,int y,ll z){
 38     b[++tot].to=y;b[tot].nx=head[x];head[x]=tot;b[tot].v=z;
 39     b[++tot].to=x;b[tot].nx=head[y];head[y]=tot;b[tot].v=z;
 40 }
 41 
 42 bool cmp(wzq i,wzq j){return i.z<j.z;}
 43 
 44 int find(int x){if(f[x]==x)return x;return f[x]=find(f[x]);}
 45 
 46 ll dep[maxn],fa[maxn][20],dp[maxn][20][2]; 
 47 void Deal(int u,int fe){
 48     dep[u]=dep[fe]+1;
 49     for(int i=head[u];i;i=b[i].nx){
 50         ll k=b[i].to;
 51         if(k==fe)continue;
 52         dp[k][0][0]=-inf;
 53         dp[k][0][1]=b[i].v;
 54         fa[k][0]=u;
 55         Deal(k,u);
 56     }
 57 }
 58 
 59 inline void cal(){
 60     for(int i=1;i<=15;i++){
 61         for(int j=2;j<=n;j++){
 62             fa[j][i]=fa[fa[j][i-1]][i-1];
 63             dp[j][i][1]=max(dp[j][i-1][1],dp[fa[j][i-1]][i-1][1]);
 64             if(dp[j][i-1][1]==dp[fa[j][i-1]][i-1][1])dp[j][i][0]=max(dp[j][i-1][0],dp[fa[j][i-1]][i-1][0]);
 65             else if(dp[j][i-1][1]>dp[fa[j][i-1]][i-1][1])dp[j][i][0]=max(dp[j][i-1][0],dp[fa[j][i-1]][i-1][1]);
 66             else if(dp[j][i-1][1]<dp[fa[j][i-1]][i-1][1])dp[j][i][0]=max(dp[j][i-1][1],dp[fa[j][i-1]][i-1][0]); 
 67         }    
 68     }
 69     return ;
 70 }
 71 
 72 ll lca(int u,int q,int va){
 73     ll nnum=0;
 74     if(dep[q]>dep[u])swap(q,u); 
 75     int gap=dep[u]-dep[q];
 76     for(int i=15;i>=0;i--){
 77         if(gap&(1<<i)){
 78             if(va>dp[u][i][1]){
 79                 nnum=max(nnum,dp[u][i][1]);    
 80             }
 81             else if(va==dp[u][i][1]){
 82                 nnum=max(nnum,dp[u][i][0]);    
 83             }
 84             u=fa[u][i];    
 85         }
 86     }
 87     for(int i=15;i>=0;i--){
 88         if(fa[u][i]!=fa[q][i]){
 89             if(va>dp[u][i][1]){
 90                 nnum=max(nnum,dp[u][i][1]);        
 91             }
 92             else if(va==dp[u][i][1]){
 93                 nnum=max(nnum,dp[u][i][0]);    
 94             }
 95             if(va>dp[q][i][1]){
 96                 nnum=max(nnum,dp[q][i][1]);        
 97             }
 98             else if(va==dp[q][i][1]){
 99                 nnum=max(nnum,dp[q][i][0]);    
100             }
101             u=fa[u][i];
102             q=fa[q][i];
103         }
104     }
105     if(va>dp[u][0][1]){
106         nnum=max(nnum,dp[u][0][1]);        
107     }
108     if(va>dp[q][0][1]){
109         nnum=max(nnum,dp[q][0][1]);    
110     }
111     return nnum;
112     
113 }
114 
115 
116 
117 int main(){
118     
119     n=read();m=read();
120     for(int i=1;i<=n;i++)f[i]=i;
121     for(int i=1;i<=m;i++){a[i].x=read();a[i].y=read();a[i].z=read();}
122     
123     sort(a+1,a+m+1,cmp);
124     for(int i=1;i<=m;i++){
125         int x1=find(f[a[i].x]),y1=find(f[a[i].y]);
126         if(x1!=y1){
127             f[x1]=y1;    
128             num+=a[i].z;
129             add(a[i].x,a[i].y,a[i].z);
130             book[i]=true;
131         }
132     }
133     
134     Deal(1,0);
135     cal();
136     
137     ll nnum=inf;
138     for(int i=1;i<=m;i++){
139         if(book[i])continue;
140         ll maxx=lca(a[i].x,a[i].y,a[i].z);
141         nnum=min(nnum,num-maxx+a[i].z);
142     }
143     write(nnum);
144     return 0;
145 }
View Code

 

以上是关于最近公共祖先--lca的主要内容,如果未能解决你的问题,请参考以下文章

二叉树最近公共祖先

二叉树最近公共祖先

最近公共祖先(LCA)问题

LCA —— 最近公共祖先

[转]LCA 最近公共祖先

LCA(最近公共祖先)