lca 例题 WK

codevs2370 小机房的树

 1 #include<iostream>
 2 #include<cstdio>
 3 #define maxn 110000
 4 using namespace std;
 5 int head[maxn],deep[maxn],sum[maxn][22],f[maxn][22];
 6 int n,m,num,ans;
 7 struct node{
 8     int to,v,pre;
 9 }e[maxn];
10 void Insert(int from,int to,int v){
11     e[++num].to=to;
12     e[num].v=v;
13     e[num].pre=head[from];
14     head[from]=num;
15 }
16 void find_deep(int from,int now,int dep,int val){
17     deep[now]=dep;f[now][0]=from;sum[now][0]=val;
18     for(int i=head[now];i;i=e[i].pre){
19         int v=e[i].to;
20         if(v!=from)find_deep(now,v,dep+1,e[i].v);
21     }
22 }
23 void find_father(){
24     for(int i=1;i<=21;i++)
25         for(int j=1;j<=n;j++)
26             f[j][i]=f[f[j][i-1]][i-1];
27     for(int i=1;i<=21;i++)
28         for(int j=1;j<=n;j++)
29             sum[j][i]=sum[f[j][i-1]][i-1]+sum[j][i-1];
30 }
31 int get(int a,int delta){
32     for(int i=0;i<=21;i++){
33         if(delta&(1<<i))ans+=sum[a][i],a=f[a][i];
34     }
35     return a;
36 }
37 int lca(int a,int b){
38     if(deep[a]<deep[b])swap(a,b);
39     if(a==b)return 0;
40     a=get(a,deep[a]-deep[b]);
41     for(int i=21;i>=0;i--){
42         if(f[a][i]!=f[b][i]){
43             ans+=sum[a][i]+sum[b][i];
44             a=f[a][i];b=f[b][i];
45         }
46     }
47     if(a!=b)ans+=sum[a][0]+sum[b][0];
48 }
49 int main(){
50     scanf("%d",&n);
51     int x,y,z;
52     for(int i=1;i<n;i++){
53         scanf("%d%d%d",&x,&y,&z);
54         Insert(x+1,y+1,z);
55         Insert(y+1,x+1,z);
56     }
57     find_deep(1,1,0,0);
58     find_father();
59     scanf("%d",&m);
60     for(int i=1;i<=m;i++){
61         scanf("%d%d",&x,&y);
62         ans=0;lca(x+1,y+1);
63         printf("%d
",ans);
64     }
65 }
View Code

cogs1439. [NOIP2013]货车运输

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 #define maxn 10010
 8 #define maxm 50010
 9 int n,m,f[maxn][20],sum[maxn][20],fa[maxn],num,p,dep[maxn],head[maxn]; 
10 bool vis[maxn];
11 struct node{
12     int f,to,v;
13 }a[maxm];
14 struct Edge{
15     int pre,v,to;
16 }e[maxm];
17 int cmp(node x,node y){return x.v>y.v;}
18 int find(int x){
19     if(fa[x]==x)return fa[x];
20     else return fa[x]=find(fa[x]);
21 }
22 int connect(int x,int y){
23     int f1=find(x),f2=find(y);
24     if(f1==f2)return 0;
25     else fa[f1]=f2;return 1;
26 }
27 void Insert(int from,int to,int v){
28     e[++num].v=v;
29     e[num].to=to;
30     e[num].pre=head[from];
31     head[from]=num;
32 }
33 void dfs(int now,int father,int deep){
34     vis[now]=1;
35     dep[now]=deep;
36     for(int i=head[now];i;i=e[i].pre){
37         int v=e[i].to;
38         if(v==father)continue;
39         f[v][0]=now;
40         sum[v][0]=e[i].v;
41         dfs(v,now,deep+1);
42     }
43 }
44 int lca(int x,int y){
45     if(x==y)return 0;
46     int ans=0x3f3f3f3f;
47     if(dep[x]<dep[y])swap(x,y);
48     for(int i=18;i>=0;i--){
49         if(dep[f[x][i]]>=dep[y]&&f[x][i]!=0)ans=min(ans,sum[x][i]),x=f[x][i];
50     }
51     if(x==y)return ans;
52     for(int i=18;i>=0;i--){
53         if(f[x][i]!=f[y][i]){
54             ans=min(ans,sum[x][i]);
55             ans=min(ans,sum[y][i]);
56             x=f[x][i];y=f[y][i];
57         }
58     }
59     ans=min(sum[x][0],ans);ans=min(sum[y][0],ans);
60     return ans;
61 }
62 int main(){
63     //freopen("Cola.txt","r",stdin);
64     freopen("truck.in","r",stdin);
65     freopen("truck.out","w",stdout);
66     memset(sum,127/3,sizeof(sum));
67     int x,y,z;
68     scanf("%d%d",&n,&m);
69     for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].f,&a[i].to,&a[i].v);
70     for(int i=1;i<=n;i++)fa[i]=i;
71     sort(a+1,a+m+1,cmp);int cnt=0;
72     for(int i=1;i<=m;i++){
73         if(connect(a[i].f,a[i].to)){
74             Insert(a[i].f,a[i].to,a[i].v);
75             Insert(a[i].to,a[i].f,a[i].v);
76             cnt++;if(cnt==n-1)break;
77         }
78     }
79     for(int i=1;i<=n;i++)if(!vis[i])dfs(i,0,1);
80     for(int j=1;(1<<j)<=n;j++)
81         for(int i=1;i<=n;i++)
82             if(f[f[i][j-1]][j-1]!=0){
83                 f[i][j]=f[f[i][j-1]][j-1];
84                 sum[i][j]=min(sum[i][j-1],sum[f[i][j-1]][j-1]);
85             }
86     scanf("%d",&p);
87     for(int i=1;i<=p;i++){
88         scanf("%d%d",&x,&y);
89         if(find(x)!=find(y)){printf("-1
");continue;}
90         printf("%d
",lca(x,y));
91     }
92 }
View Code

hdu2586

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <vector>
 5 using namespace std;
 6 vector<int> v[41000];
 7 vector<int> w[41000];
 8 int f[41000][21];//f[i][j]表示i点向上2^j层的祖先 
 9 int sum[41000][21];//g[i][j]表示i点到从i向上2^j层的祖先的距离 
10 int dep[41000];
11 int n,m;
12 void dfs(int pos,int pre,int depth)
13 {
14     dep[pos]=depth;
15     for(int i=0;i<v[pos].size();i++)
16     {
17         int t=v[pos][i];
18         if(t==pre) continue;
19         f[t][0]=pos;
20         sum[t][0]=w[pos][i];
21         dfs(t,pos,depth+1);
22     }
23 }
24 int query(int a,int b)
25 {
26     int Sum=0;
27     if(dep[a]<dep[b]) swap(a,b);//深度较深的点 
28     for(int i=20;i>=0;i--)//找到a在深度dep[b]处的祖先 
29     {
30         if(dep[f[a][i]]>=dep[b])
31         {
32             Sum+=sum[a][i];//a到该祖先的距离 
33             a=f[a][i];
34         }
35     }
36     if(a==b) return Sum;//挪到相同深度后如果在同一点直接return 
37     int x;
38     for(int i=20;i>=0;i--)//否则a和b一起往上跳 
39     {
40         if(f[a][i]!=f[b][i])
41         {
42             Sum+=sum[a][i];
43             a=f[a][i];
44             Sum+=sum[b][i];
45             b=f[b][i];
46         }
47     }
48     return Sum+sum[a][0]+sum[b][0];//最后跳到最近公共祖先的下一层,所以要再加上上一层 
49 }
50 int main()
51 {
52     int T;
53     cin>>T;
54     while(T--)
55     {
56         scanf("%d%d",&n,&m);
57         memset(dep,-1,sizeof(dep));
58         memset(f,0,sizeof(f));
59         memset(sum,0,sizeof(sum));
60         for(int i=0;i<n;i++)//md
61             v[i].clear(),w[i].clear();
62         for(int i=1;i<n;i++)
63         {
64             int x,y,c;
65             cin>>x>>y>>c;
66             v[x].push_back(y);
67             w[x].push_back(c);
68             v[y].push_back(x);
69             w[y].push_back(c);
70         }
71         int xxx=v[1].size();
72         dfs(1,0,1);//dfs处理出每个点的深度,以及各种... 
73     
74         for(int i=1;1<<i<=n;i++)
75             for(int j=1;j<=n;j++)
76                 f[j][i]=f[f[j][i-1]][i-1],
77                 sum[j][i]=sum[f[j][i-1]][i-1]+sum[j][i-1];
78         for(int i=1;i<=m;i++)
79         {
80             int x,y;
81             cin>>x>>y;
82             if(x==y) cout<<"0"<<endl;
83             else cout<<query(x,y)<<endl;
84         }
85     }
86     return 0;
87 }
View Code

洛谷3379

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 #define maxn 500010
 5 int n,m,s,f[maxn][22],deep[maxn],head[maxn],num;
 6 struct node{
 7     int to,pre;
 8 }e[maxn<<1];
 9 int qread(){
10     int x=0,j=1;
11     char ch=getchar();
12     while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();}
13     while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
14     return x*j;
15 }
16 void Insert(int from,int to){
17     e[++num].to=to;
18     e[num].pre=head[from];
19     head[from]=num;
20 }
21 void find_deep(int from,int now,int dep){
22     f[now][0]=from;deep[now]=dep;
23     for(int i=head[now];i;i=e[i].pre){
24         int v=e[i].to;
25         if(v!=from){
26             find_deep(now,v,dep+1);
27         }
28     }
29 }
30 void find_father(){
31     for(int j=1;j<=21;j++)
32         for(int i=1;i<=n;i++)
33             f[i][j]=f[f[i][j-1]][j-1];
34 }
35 int get(int a,int delta){
36     for(int i=0;i<=21;i++){
37         if(delta&(1<<i))a=f[a][i];
38     }return a;
39 }
40 int lca(int a,int b){
41     if(deep[a]<deep[b])swap(a,b);
42     a=get(a,deep[a]-deep[b]);
43     if(a==b) return a;
44     for(int i=21;i>=0;i--){
45         if(f[a][i]!=f[b][i]){
46             a=f[a][i],b=f[b][i];
47         }
48     }
49     return f[a][0];
50 }
51 int main(){
52     n=qread(),m=qread(),s=qread();
53     int x,y;
54     for(int i=1;i<=n-1;i++){
55         x=qread();y=qread();
56         Insert(x,y);
57         Insert(y,x);
58     }
59     find_deep(s,s,0);
60     find_father();
61     for(int i=1;i<=m;i++){
62         x=qread();y=qread();
63         int ans=lca(x,y);
64         printf("%d
",ans);
65     }
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/lyqlyq/p/6883145.html