「P1967 [NOIP 2013 提高组] 货车运输」题解
1.「P3627 [APIO2009] 抢掠计划(ATM)」题解2.「P3225 [HNOI2012] 矿场搭建」题解3.「P3214 [HNOI2011] 卡农」题解4.「旅游景点 Tourist Attractions」题解5.「ARC_172_A_Chocolate」题解
6.「P1967 [NOIP 2013 提高组] 货车运输」题解
7.「佳佳的 Fibonacci」题解8.「Fibonacci 前 n 项和」题解9.「P10668 BZOJ2720 [Violet 5] 列队春游」题解10.「P7394 「TOCO Round 1」History」题解11.「ABC375」题解12.「P6054 [RC-02] 开门大吉」题解13.「最小割树」学习笔记 & 「P4897 【模板】最小割树(Gomory-Hu Tree)」 题解题目描述与思路
简化题目:
求
与之前的最短路最大的不同是这道题是多源最短路,那么
用
所以我们需要用到
首先展示
void kru() { stable_sort(e+1,e+1+m,cmp); cnt=n; for(int i=1;i<=m;i++) { int a=find(e[i].x),b=find(e[i].y); if(a==b) continue; f[a]=f[b]=++cnt; g[a].push_back(cnt),g[cnt].push_back(a), g[b].push_back(cnt),g[cnt].push_back(b); w[cnt]=e[i].w; if(++tot==n-1) break; } root=n+tot; }
首先排序一下,注意这道题是
有三个重要点
- 和正常的最小生成树不同,我们最后只需要输出两点的最近公共祖先的点权,但我们实则求的是对应的边权,就需要将边权转换为点权。不妨将相连的两点
, 中间插入一个点,让这个点的点权为 的边权,并使这个点成为 和 的祖先- 为什么让他成为这两个点的祖先也是显而易见的,我们最后输出最近公共祖先的权值,只有类似这个新点的权值,他才不是
,看完全部代码后会理解得更清晰
- 为什么让他成为这两个点的祖先也是显而易见的,我们最后输出最近公共祖先的权值,只有类似这个新点的权值,他才不是
- 我们需要搞出来树根
代码里最后有一行 为什么这么做呢?他重构树之后显然是有 的,但他最后一个点不可能是森林(不然他无父无母的都遍历不到这个点),相当重要的,否则只有15分,后面 时有用 - 某个脑残问题,看到那个
没有,改成 , 就没了
然后快乐的打完
并查集如果用我这种方法别忘了
代码呈上
#include<bits/stdc++.h> #define endl '\n' #define int long long using namespace std; const int N=5e5+1; template<typename Tp> inline void read(Tp&x) { x=0;register bool z=1; register char c=getchar(); for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0; for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48); x=(z?x:~x+1); } int n,m,q,cnt,root,tot; int w[N],f[N],fa[N],dep[N],sz[N],son[N],top[N]; vector<int>g[N]; struct aa{int x,y,w;}e[N]; bool cmp(aa s1,aa s2){return s1.w>s2.w;} int find(int x) { if(f[x]!=x) f[x]=find(f[x]); return f[x]; } void kru() { stable_sort(e+1,e+1+m,cmp); cnt=n; for(int i=1;i<=m;i++) { int a=find(e[i].x),b=find(e[i].y); if(a==b) continue; f[a]=f[b]=++cnt; g[a].push_back(cnt),g[cnt].push_back(a), g[b].push_back(cnt),g[cnt].push_back(b); w[cnt]=e[i].w; if(++tot==n-1) break; } root=n+tot; } void dfs1(int x,int t) { fa[x]=t,dep[x]=dep[t]+1,sz[x]=1; for(int y:g[x]) if(y!=t) { dfs1(y,x); sz[x]+=sz[y]; if(sz[son[x]]<sz[y]) son[x]=y; } } void dfs2(int x,int t) { top[x]=t; if(!son[x]) return ; dfs2(son[x],t); for(int y:g[x]) if(y!=son[x]&&y!=fa[x]) dfs2(y,y); } int lca(int x,int y) { for(;top[x]!=top[y];x=fa[top[x]]) if(dep[top[x]]<dep[top[y]]) swap(x,y); return dep[x]<dep[y]?x:y; } signed main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int x,y; read(n),read(m); for(int i=1;i<=n+m;i++) f[i]=i; for(int i=1;i<=m;i++) read(e[i].x),read(e[i].y),read(e[i].w); kru(),dfs1(root,0),dfs2(root,root); read(q); while(q--) read(x),read(y), cout<<((find(x)!=find(y))?-1:w[lca(x,y)])<<endl; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具