最近公共祖先TarjanTarjan求LCA练习
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近公共祖先TarjanTarjan求LCA练习相关的知识,希望对你有一定的参考价值。
Tarjan求LCA
这是一篇非常好的讲解,靠这个文章搞懂的~
1 void tarjan(int u) 2 { 3 vis[u]=1; 4 for(int i=0;i<edge[u].size();i++) 5 { 6 int v=edge[u][i]; 7 if(vis[v] == 0) 8 { 9 tarjan(v); 10 p[v]=u; 11 } 12 } 13 for(int i=0;i<qy[u].size();i++) 14 { 15 int v=qy[u][i].v,id=qy[u][i].id; 16 if(vis[v] == 1){ 17 ans[id]=find(v); 18 } 19 } 20 }
例题1:商务旅行
题目描述 Description
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
输入描述 Input Description
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
输出描述 Output Description
在输出文件中输出该商人旅行的最短时间。
样例输入 Sample Input
5
1 2
1 5
3 5
4 5
4
1
3
2
5
样例输出 Sample Output
7
俺的题解
每个城市都有道路连接,且道路没有方向。于是,这是棵树= =
树上求最短路:dfs求出deep,再求出LCA。
比较基础。
傻X错误:Tarjan判断询问是否访问过时,[v]写成了[i]...
询问的时候可以再减小内存不用存数组,下次注意。
俺的代码
1 /* 2 ??:monkeytutula 3 ??:p1036 ???? 4 */ 5 6 /* 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 #include<vector> 12 using namespace std; 13 int n,m,tim=1,ans=0,q[30700],p[30070],pr[30070],deep[30070]; 14 int lca[30700]; 15 bool vis[30700]; 16 struct node 17 { 18 int v,id; 19 node(int v1=0,int id1=0): v(v1),id(id1) {} 20 }; 21 vector<int> edge[60070]; 22 vector<node> query[60070]; 23 void dfs(int s,int dp) 24 { 25 deep[s]=dp; 26 for(int i=0;i<edge[s].size();i++) 27 { 28 if(!vis[edge[s][i]]){ 29 vis[edge[s][i]]=1; 30 dfs(edge[s][i],dp+1); 31 } 32 } 33 } 34 int find(int x) 35 { 36 if(p[x] == x) 37 return x; 38 return p[x]=find(p[x]); 39 } 40 void tarjan(int u) 41 { 42 p[u]=u; 43 pr[u]=tim++; 44 for(int i=0;i<edge[u].size();i++) 45 { 46 int v=edge[u][i]; 47 if(pr[v] == 0){ 48 tarjan(v); 49 p[v]=u; 50 } 51 } 52 for(int i=0;i<query[u].size();i++) 53 { 54 int v=query[u][i].v; 55 if(pr[v] != 0){ 56 lca[query[u][i].id]=find(v); 57 } 58 } 59 } 60 int main() 61 { 62 scanf("%d",&n); 63 for(int i=1;i<n;i++) 64 { 65 int x,y; 66 scanf("%d%d",&x,&y); 67 edge[x].push_back(y); 68 edge[y].push_back(x); 69 } 70 for(int i=0;i<=n;i++)p[i]=i; 71 vis[1]=1; 72 dfs(1,1); 73 scanf("%d",&m); 74 for(int i=1;i<=m;i++) 75 { 76 scanf("%d",&q[i]); 77 } 78 for(int i=2;i<=m;i++) 79 { 80 query[q[i-1]].push_back(node(q[i],i)); 81 query[q[i]].push_back(node(q[i-1],i)); 82 } 83 tarjan(1); 84 int ans=0; 85 for(int i=2;i<=m;i++) 86 { 87 ans+=(deep[q[i-1]]+deep[q[i]]-2*deep[lca[i]]); 88 } 89 printf("%d",ans); 90 return 0; 91 }
以上是关于最近公共祖先TarjanTarjan求LCA练习的主要内容,如果未能解决你的问题,请参考以下文章