尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

[WC2006] 水管局长

[WC2006] 水管局长
📅 发布时间:2026/6/19 12:09:37

显然,这道题需要维护一棵最小生成树,支持动态删边,查询链上最大值。查询链上最大值可以倍增维护,但是本题 \(n\) 较小,直接暴力往上跳也是可过的。
接下来就是如何动态维护最小生成树的问题了。对于一般图的最小生成树求解,我们有 \(O(m\log m)\) 的 Kruskal 算法和 \(O(n^2)\) 的 Prim 算法。然而这两种方法都是静态的,无法支持动态加(删)边,是否有方法能高效地动态维护最小生成树呢?
题解里全都是 LCT,可我不会啊?于是开发出了一些新方法。

方法一

数据范围中有一个特别显眼的地方:宣布报废的水管不超过 \(5 \times 10^3\) 条。那我们就考虑暴力重构,设重构次数为 \(T\),显然 \(O(Tm\log m)\) 的复杂度不可接受,但是我们可以想到:每次重构都排序是不必要的,可以一开始对所有边排序,后续每次 Kruskal 时只 \(O(m)\) 遍历每条边,检查当前边是否被删除,若被删除直接跳过即可。单次重构时间复杂度 \(\Theta(n+n\alpha(n)+m)\),理论上已经可过了,但是由于常数较大最终未能通过。

方法二

既然正着过不去,我们考虑将整个过程倒着来,改为加边操作,考虑加边的过程:先将 \((u,v)\) 加入到最小生成树中,变成一棵基环树,然后断掉环内边权最大的边即可。换成更好维护的方式:查询链 \(u,v\) 上的最大值,若其小于 \(w(u,v)\),则不将其加入最小生成树,反之则加入,并删除原来链 \(u,v\) 上的最大值所对的边。高效删边可以通过将邻接表的 std::vector 换成 std::set 实现。然后再 dfs 一遍重构父子关系。这样,我们就把单次重构的复杂度降为了 \(\Theta(n+\log n)\)。

code

#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
template<typename T>
inline void read(T &x){bool f=0;x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}if(f) x=~x+1;
}
template<typename T,typename...Args>
void read(T &x,Args &...args){read(x);read(args...);}
constexpr int N=1e3+10,M=1e5+10;
struct Que{int op,u,v;}ask[M];
struct Edge{int v,w;bool operator<(const Edge &x)const{return v<x.v;}
};
set<Edge> g[N];
int n,m,q,fa[N],val[N],dep[N];
int w[N][N],boss[N],ans[M];
struct edge{int u,v,t;bool operator<(const edge &x)const{return w[u][v]<w[x.u][x.v];}
}e[M];
bool del[N][N];
int find(int x){return boss[x]==x?x:boss[x]=find(boss[x]);}
void dfs(int u,int f){dep[u]=dep[f]+1;for(auto &[v,w]:g[u]){if(v==f) continue;fa[v]=u;val[v]=w;dfs(v,u);}
}
inline void build(){for(int i=1;i<=n;i++) boss[i]=i;int cnt=0;for(int i=1;i<=m;i++){int u=e[i].u,v=e[i].v;if(del[u][v]) continue;int val=w[u][v];u=find(u),v=find(v);if(u==v) continue;boss[u]=v;g[e[i].u].insert({e[i].v,val});g[e[i].v].insert({e[i].u,val});if(++cnt==n-1) break;}dfs(1,0);
}
typedef pair<int,edge> pr;
inline pr query(int x,int y){pr res={};while(x!=y){if(dep[x]<dep[y]) swap(x,y);if(val[x]>res.first)res={val[x],{x,fa[x]}};x=fa[x];}return res;
}
int main(){read(n,m,q);for(int i=1,t;i<=m;i++){read(e[i].u,e[i].v,t);w[e[i].u][e[i].v]=w[e[i].v][e[i].u]=t;}for(int i=1;i<=q;i++){read(ask[i].op,ask[i].u,ask[i].v);if(ask[i].op==2)del[ask[i].u][ask[i].v]=del[ask[i].v][ask[i].u]=1;}sort(e+1,e+1+m);build();for(int i=q;i;i--){int u=ask[i].u,v=ask[i].v;pr res=query(u,v);if(ask[i].op==1) ans[i]=res.first;else{if(res.first<=w[u][v]) continue;edge old=res.second;g[old.u].erase({old.v,w[old.u][old.v]});g[old.v].erase({old.u,w[old.u][old.v]});g[u].insert({v,w[u][v]});g[v].insert({u,w[u][v]});dfs(1,0);}}for(int i=1;i<=q;i++) if(ans[i]) printf("%d\n",ans[i]);return 0;
}

相关新闻

  • YOLO入门理解 3YOLOv1 思路与细节
  • 清除win+r“运行”对话框中的历史记录
  • YOLO入门理解 基础概念

最新新闻

  • DSS-GAN:基于Mamba的高效生成对抗网络架构解析
  • 解密HarmonyOS签名适配:5步实现MicroG无缝集成终极指南
  • 终极开源AI数字人平台:3步实现离线视频创作的完整指南
  • 2026年值得信赖的装修公司推荐,体验服务品质之选 - mypinpai
  • 告别抢票焦虑!95%成功率的大麦自动抢票神器完全指南
  • ExtCore实战案例:如何从零开始构建一个完整的模块化CMS

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号