标签:\n return tin 开始 continue roo head -- iostream
这个题面真的难受,看了好久才看懂。。。
题目大意:
给出一个无环图,求图中任意两点的距离(刚开始还以为是最短路。。。)
好像没有什么思路,爆搜?肯定超时,那可怎么办?
其实这道题可以用LCA来解决。。。(要不是前一题做的LCA还真想不到。。。)
首先,我们还是先找根,但是这道题可能不太好找,所以我们就人为的规定输入的x y中x是爸爸,所以找根就找没有出现在y的位置的结点(就是没有爸爸的节点)
接着我们预处理出每一个节点向上跳2的i次幂到达的位置,以及它到根节点的路径(显然只有一条,题面里给的),还有它的深度。
接着我们利用倍增法求出两个点的LCA(具体实现看代码)
答案就是dis[x]+dis[y]-2*dis[LCA(x,y)] x,y为询问的两个点(想一想正确性,还是比较显然的)
最后,附上本题代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define maxn 40000 5 using namespace std; 6 7 struct EDGE 8 { 9 int nxt,to,v; 10 }; 11 EDGE edge[maxn*2+5]; 12 int T,n,root,cnt,m; 13 int head[maxn+5],dep[maxn+5],dis[maxn+5]; 14 int f[maxn+5][25]; 15 bool vis[maxn+5]; 16 17 void add(int x,int y,int z) 18 { 19 edge[++cnt].to=y; 20 edge[cnt].v=z; 21 edge[cnt].nxt=head[x]; 22 head[x]=cnt; 23 } 24 void pre_fir(int u,int fa) 25 { 26 dep[u]=dep[fa]+1; 27 for(int i=0; i<=22; i++) 28 { 29 f[u][i+1]=f[f[u][i]][i]; 30 } 31 for(int i=head[u]; i; i=edge[i].nxt) 32 { 33 if(edge[i].to==fa) 34 { 35 continue; 36 } 37 dis[edge[i].to]=dis[u]+edge[i].v; 38 f[edge[i].to][0]=u; 39 pre_fir(edge[i].to,u); 40 } 41 } 42 int LCA(int x,int y) 43 { 44 if(dep[x]<dep[y]) 45 { 46 swap(x,y); 47 } 48 for(int i=22; i>=0; i--) 49 { 50 if(dep[f[x][i]]>=dep[y]) 51 { 52 x=f[x][i]; 53 } 54 if(x==y) 55 { 56 return x; 57 } 58 } 59 for(int i=22; i>=0; i--) 60 { 61 if(f[x][i]!=f[y][i]) 62 { 63 x=f[x][i]; 64 y=f[y][i]; 65 } 66 } 67 return f[x][0]; 68 } 69 int main() 70 { 71 scanf("%d",&T); 72 while(T--) 73 { 74 memset(vis,0,sizeof(vis)); 75 memset(edge,0,sizeof(edge)); 76 memset(f,0,sizeof(f)); 77 memset(dep,0,sizeof(dep)); 78 memset(head,0,sizeof(head)); 79 memset(dis,0,sizeof(dis)); 80 cnt=0; 81 scanf("%d%d",&n,&m); 82 for(int i=1; i<=n-1; i++) 83 { 84 int x,y,z; 85 scanf("%d%d%d",&x,&y,&z); 86 vis[y]=1; 87 add(x,y,z); 88 add(y,x,z); 89 } 90 for(int i=1; i<=n; i++) 91 { 92 if(vis[i]==0) 93 { 94 root=i; 95 break; 96 } 97 } 98 pre_fir(root,0); 99 for(int i=1; i<=m; i++) 100 { 101 int a,b; 102 scanf("%d%d",&a,&b); 103 printf("%d\n",dis[a]+dis[b]-2*dis[LCA(a,b)]); 104 } 105 } 106 return 0; 107 }
标签:\n return tin 开始 continue roo head -- iostream
原文地址:https://www.cnblogs.com/yufenglin/p/10575524.html