LCA

How far away ?

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.

Input

First line is a single integer T(T10), indicating the number of test cases.
For each test case,in the first line there are two numbers n(2n40000) and m(1m200),the number of houses and the number of queries. The following n1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.

Output

For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.

Sample Input

2 3 2 1 2 10 3 1 15 1 2 2 3 2 2 1 2 100 1 2 2 1

Sample Output

10 25 100 100

Source

ECJTU 2009 Spring Contest

题目链接

hdu2586

题目描述

给定一个生成树,求任意两个结点的距离

解题思路

1.树上倍增法

  • 时间复杂度((n+m)log(n))

2.tarjan优化
本质:一种离线做法,并查集对“向上标记法”的优化

  • 时间复杂度o(n+m)

代码

  • 常规代码
#include<bits/stdc++.h> using namespace std; const int N=40010; vector<pair<int,int>>adj[N];//邻接表 int dist[N],d[N],f[N][20];//dist[i]:结点i到根节点的距离,d[i]:结点i的深度, //f[i][j]:结点i向上走2^j步到达的结点 int T,n,m,x,y,z,t; void bfs() { queue<int>q; q.push(1);//设1为根节点 dist[1]=0; d[1]=1; while(q.size()) { int u=q.front(); q.pop(); for(auto p:adj[u]) { int v=p.first,w=p.second; if(dist[v]||v==1)continue;//注意v==1的情况 d[v]=d[u]+1; dist[v]=dist[u]+w; f[v][0]=u; for(int i=1;i<=t;i++)f[v][i]=f[f[v][i-1]][i-1];//注意,这里是递推式子,应该从小到大 q.push(v); } } } int lca(int x,int y) { if(d[x]>d[y])swap(x,y); for(int i=t;i>=0;i--) if(d[f[y][i]]>=d[x])y=f[y][i]; if(x==y)return x; for(int i=t;i>=0;i--) if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0]; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); t=log(n)/log(2)+1; for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); adj[x].emplace_back(y,z); adj[y].emplace_back(x,z); } bfs();//预处理 while(m--) { scanf("%d%d",&x,&y); printf("%d\n",dist[x]+dist[y]-2*dist[lca(x,y)]); } for(int i=1;i<=n;i++)d[i]=0,dist[i]=0,adj[i].clear();//多组测试,清零 } return 0; }
  • 高效代码
#include<bits/stdc++.h> using namespace std; const int N=40010; vector<int>query[N],query_id[N]; vector<pair<int,int>>adj[N]; int T,n,m,x,y,z,fa[N],dist[N],ans[210],vis[N];//ans记录答案,v标记是否遍历 void add_query(int u,int v,int id)//query与query_id同步,离线记录 { query[u].emplace_back(v),query_id[u].emplace_back(id); query[v].emplace_back(u),query_id[v].emplace_back(id); } int get(int x) { if(x==fa[x])return x; return fa[x]=get(fa[x]); } void tarjan(int u) { vis[u]=1; for(auto p:adj[u]) { int v=p.first,w=p.second; if(vis[v])continue; dist[v]=dist[u]+w; tarjan(v); fa[v]=u; } for(int i=0;i<query[u].size();i++) { int v=query[u][i],id=query_id[u][i]; if(vis[v]==2)//已回溯的点才有更新过的father { int lca=get(v); ans[id]=dist[u]+dist[v]-2*dist[lca]; } } vis[u]=2; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { fa[i]=i; dist[i]=vis[i]=0; adj[i].clear(); query[i].clear(); query_id[i].clear(); } for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); adj[x].emplace_back(y,z); adj[y].emplace_back(x,z); } for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(x==y)ans[i]=0; else add_query(x,y,i); } tarjan(1); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/15139481.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(48)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示