模板倍增LCA 求树上两点距离 hdu2586
http://acm.hdu.edu.cn/showproblem.php?pid=2586
课上给的ppt里的模板是错的,wa了一下午orz。最近总是被坑啊。。。
题解:树上两点距离转化为到根的距离之和减去重复部分,相当于前缀和
dis[x] + dis[y] - 2ll * dis[LCA(x, y)]
#define _CRT_SECURE_NO_WARNINGS #include<cmath> #include<iostream> #include<stdio.h> #include<algorithm> #include<cstring> #include<stack> #include<vector> #include<string.h> using namespace std; #define rep(i,t,n) for(int i =(t);i<=(n);++i) #define per(i,n,t) for(int i =(n);i>=(t);--i) #define mmm(a,b) memset(a,b,sizeof(a)) #define eps 1e-6 #define pb push_back typedef long long ll; stack <int> dl; const int maxn=1e5+5; int f[maxn][16]; int fa[maxn]; ll dis[maxn]; int dep[maxn]; int n, m; vector<pair<int,ll> > E[maxn]; void dfs(int rt,int p) { for (int i = 0; i < E[rt].size(); i++) { pair<int,int> v = E[rt][i]; if (v.first == p)continue; fa[v.first] =rt ; dep[v.first] =dep[rt]+1 ; dis[v.first] = dis[rt] + v.second; dfs(v.first, rt); } } void Init_LCA() { for (int j = 0; (1 << j) <= n; ++j) for (int i = 1; i <= n; ++i) f[i][j] = -1; for (int i = 1; i <= n; ++i) f[i][0] = fa[i]; for (int j = 1; (1 << j) <= n; ++j) for (int i = 1; i <= n; ++i) if (f[i][j - 1] != -1) f[i][j] = f[f[i][j - 1]][j - 1]; } int LCA(int x, int y) { if (dep[x] < dep[y]) swap(x, y); int i, lg; for (lg = 0; (1 << lg) <= dep[x]; ++lg); --lg; /// 使x往上走直到和y在同一水平线上; for (i = lg; i >= 0; --i) if (dep[x] - (1 << i) >= dep[y]) x = f[x][i]; if (x == y) return x; /// 此时x,y在同一水平线上,使x,y同时以相同的速度(2^j)往上走; for (i = lg; i >= 0; --i) if (f[x][i] != -1 && f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; return fa[x]; } int main() { int t; cin >> t; while (t--) { cin >> n >> m; rep(i, 1, n)E[i].clear(); //mmm(dis, 0); mmm(fa, 0); mmm(f, 0); mmm(dep, 0); rep(i, 1, n-1) { int x, y; ll z; scanf("%d%d%lld", &x, &y, &z); //f[x][0] = y; E[x].push_back(make_pair(y,z)); E[y].push_back(make_pair(x,z)); } dis[1] = 0; //fa[1] = 1; //dep[1] = 0; dfs(1, -1); Init_LCA(); rep(i, 1, m) { int x, y; scanf("%d%d", &x, &y); printf("%lld\n", dis[x] + dis[y] - 2ll * dis[LCA(x, y)]); } //cout << endl; } cin >> n; return 0; }/* 2 5 2 1 2 10 2 3 10 3 4 10 4 5 10 1 5 5 3 */
成功的路并不拥挤,因为大部分人都在颓(笑)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署