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 51111 13 struct node 14 { 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 }
是有问题的,但是数据弱所以没爆出来。
正确形式:
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 51111 11 struct node 12 { 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 }
可以仔细体验差别。
因为 在其中吃了大亏。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 }
随性Code