首页 > 代码库 > LCA 笔记

LCA 笔记

简述这几天的LCA 心得:

LCA有两种做法:离线 or 在线

先学的离线;

原理博客很多。

我写得两道题,已经模板。

HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2586

HDU :http://acm.hdu.edu.cn/showproblem.php?pid=2874 2874;

之前一份板子:

技术分享
 1 #pragma comment(linker, "/STACK:10240000000,10240000000")   2  3 #include<iostream> 4 #include<stdio.h> 5 #include<string.h> 6 #include<cmath> 7 #include<algorithm> 8 #include<string> 9 #include<vector>10 using namespace std;11 12 #define N 5111113 struct node14 {15     int v,w;16 17     node(int vv,int ww)18     {19        v=vv;20        w=ww;21     }22 };23 int f[N],dis[N],ans[N],vis[N],n;24 vector<node>mp[N];25 vector<node>q[N];26 27 int find(int x)28 {29     if (f[x]!=x)  f[x]=find(f[x]);30     return f[x];31 }32 33 void lca(int u)34 {35     for (int i=0;i<mp[u].size();i++)36     {37         int v=mp[u][i].v;38         if (vis[v]) continue;39         vis[v]=1;40 41         dis[v]=dis[u]+mp[u][i].w;42         lca(v);43         f[v]=u;44         for (int j=0;j<q[v].size();j++)45         {46             int c=q[v][j].v;47             if (vis[c]&&ans[q[v][j].w]==-1)48             {49                 if (v==c) ans[q[v][j].w]=0;50                 else ans[q[v][j].w]=dis[v]+dis[c]-2*dis[find(c)];51             }52         }53     }54 }55 56 int main()57 {58     int T;59     scanf("%d",&T);60     while (T--)61     {62         int m;63         scanf("%d%d",&n,&m);64         for (int i=1;i<=n;i++)65         {66             mp[i].clear();67             q[i].clear();68             ans[i]=-1;69             f[i]=i;70             vis[i]=0;71         }72         for (int i=1;i<n;i++)73         {74             int a,b,c;75             scanf("%d%d%d",&a,&b,&c);76             mp[a].push_back(node(b,c));77             mp[b].push_back(node(a,c));78         }79         for (int i=1;i<=m;i++)80         {81             int a,b;82             scanf("%d%d",&a,&b);83             q[a].push_back(node(b,i));84             q[b].push_back(node(a,i));85         }86         vis[1]=1;87         dis[1]=0;88         lca(1);89 90         for (int i=1;i<=m;i++)91             printf("%d\n",ans[i]);92     }93     return 0;94 }
View Code

是有问题的,但是数据弱所以没爆出来。

正确形式:

技术分享
 1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<string> 7 #include<vector> 8 using namespace std; 9 10 #define N 5111111 struct node12 {13     int v,w;14 15     node(int vv,int ww)16     {17        v=vv;18        w=ww;19     }20 };21 int f[N],dis[N],ans[N],vis[N],n;22 vector<node>mp[N];23 vector<node>q[N];24 25 int find(int x)26 {27     if (f[x]!=x)  f[x]=find(f[x]);28     return f[x];29 }30 31 void lca(int u)32 {33     for (int i=0;i<mp[u].size();i++)34     {35         int v=mp[u][i].v;36         if (vis[v]) continue;37         vis[v]=1;38 39         dis[v]=dis[u]+mp[u][i].w;40         lca(v);41         f[v]=u;42     }43         for (int j=0;j<q[u].size();j++)44         {45             int c=q[u][j].v;46             if (vis[c]&&ans[q[u][j].w]==-1)47             {48                 if (u==c) ans[q[u][j].w]=0;49                 else ans[q[u][j].w]=dis[u]+dis[c]-2*dis[find(c)];50             }51         }52 53 }54 55 int main()56 {57     int T;58     scanf("%d",&T);59     while (T--)60     {61         int m;62         scanf("%d%d",&n,&m);63         for (int i=1;i<=n;i++)64         {65             mp[i].clear();66             q[i].clear();67             ans[i]=-1;68             f[i]=i;69             vis[i]=0;70         }71         for (int i=1;i<n;i++)72         {73             int a,b,c;74             scanf("%d%d%d",&a,&b,&c);75             mp[a].push_back(node(b,c));76             mp[b].push_back(node(a,c));77         }78         for (int i=1;i<=m;i++)79         {80             int a,b;81             scanf("%d%d",&a,&b);82             q[a].push_back(node(b,i));83             q[b].push_back(node(a,i));84         }85         vis[1]=1;86         dis[1]=0;87         lca(1);88 89         for (int i=1;i<=m;i++)90             printf("%d\n",ans[i]);91     }92     return 0;93 }
View Code

可以仔细体验差别。

因为 在其中吃了大亏。HDU 2874 (都是简单题)卡了三天 。想想算法没错 ,果然是板子的问题。

换一种写法也可以,询问在递归前面也可以。

  1 #include<iostream>  2 #include<stdio.h>  3 #include<string.h>  4 #include<cmath>  5 #include<algorithm>  6 #include<string>  7 #include<vector>  8 using namespace std;  9  10 #define N 21111 11 typedef long long ll; 12 struct node 13 { 14     int v,w; 15     node(int vv=0,int ww=0) 16     { 17        v=vv; 18        w=ww; 19     } 20 }; 21  22 int f[N]; 23 int ans[1110000],dis[N]; 24 int vis[N],mark[N]; 25  26 vector<node>mp[N]; 27 vector<node>q[N]; 28  29 int find(int x) 30 { 31     if (f[x]!=x)  f[x]=find(f[x]); 32     return f[x]; 33 } 34  35 void lca(int u) 36 { 37  38     for (int i=0;i<q[u].size();i++) 39     { 40         int c=q[u][i].v; 41         int w=q[u][i].w; 42         if (vis[c]&&ans[w]==-1&&mark[find(c)]!=1) 43         { 44             ans[w]=dis[u]+dis[c]-2*dis[find(c)]; 45         } 46     } 47  48       for (int i=0;i<mp[u].size();i++) 49     { 50         int v=mp[u][i].v; 51         if (vis[v]) continue; 52         vis[v]=1; 53         dis[v]=dis[u]+mp[u][i].w; 54         lca(v); 55         f[v]=u; 56         /* 57        for (int j=0;j<q[v].size();j++) 58         { 59             int c=q[v][j].v; 60             int w=q[v][j].w; 61             if (vis[c]&&ans[w]==-1&&mark[find(c)]!=1) 62             { 63                 // if (v==c) ans[w]=0; 64                 // else 65                  ans[w]=dis[v]+dis[c]-2*dis[find(c)]; 66             } 67         } 68         */ 69  70     } 71 } 72  73 int main() 74 { 75     // freopen("input.txt","r",stdin); 76     // freopen("output1.txt","w",stdout); 77      int n,m,C; 78      while (scanf("%d%d%d",&n,&m,&C)!=EOF) 79      { 80         for (int i=0;i<=n;i++) 81         { 82             f[i]=i; 83             mp[i].clear(); 84             q[i].clear(); 85             vis[i]=0; 86             dis[i]=0; 87             mark[i]=0; 88         } 89         for (int i=1;i<=C;i++) ans[i]=-1; 90         for (int i=1;i<=m;i++) 91         { 92             int a,b,c; 93             scanf("%d%d%d",&a,&b,&c); 94             mp[a].push_back(node(b,c)); 95             mp[b].push_back(node(a,c)); 96         } 97         for (int i=1;i<=C;i++) 98         { 99             int a,b;100             scanf("%d%d",&a,&b);101             q[a].push_back(node(b,i));102             q[b].push_back(node(a,i));103         }104 105         for (int i=1;i<=n;i++)106         if (!vis[i])107         {108             vis[i]=1;109             dis[i]=0;110             lca(i);111             mark[i]=1;112         }113 114          for (int i=1;i<=n;i++)115          for (int j=0;j<q[i].size();j++)116          {117              int u=i;118              int v=q[i][j].v;119              int w=q[i][j].w;120              if (find(u)!=find(v)) ans[w]=-1;121          }122 123 124             for (int i=1;i<=C;i++)125             if (ans[i]==-1) printf("Not connected\n");126             else printf("%d\n",ans[i]);127 128     }129     return 0;130 }

 

LCA 笔记