【XSY2515】管道(pipe)(最小生成树+倍增lca)
题面
Description
给你一个城市下水道网络图,你需要选出一些管道,使得在只使用这些管道的情况下,令整个网络联通,并且花费最小。
网络图可以看做是无向连通图,有nnn个节点和mmm条边,每条边连接uiu_iui和viv_ivi,选择的花费是wiw_iwi。
不巧的是,由于某些原因,现在市政局要求选定某条特定的边管道,你的任务是求出对于某一条边,在选择这条管道的前提下的最小花费。
Input
第111行包含两个整数nnn,mmm,表示点数和边数。
第222~m+1m+1m+1行每行三个整数uiu_iui,viv_ivi,wiw_iwi,表示有一条管道连接uiu_iui和viv_ivi,费用为wiw_iwi。
Output
输出m行,每行一个整数,表示选择第i条管道的前提下的最小花费。
管道按输入的顺序编号为111~mmm。
Sample Input
5 7
1 2 3
1 3 1
1 4 5
2 3 2
2 5 3
3 4 2
4 5 4
Sample Output
9
8
11
8
8
8
9
Hint
对于20%20\%20%的数据,n<=1000n<=1000n<=1000,m<=2000m<=2000m<=2000
对于另外20%20\%20%的数据,m<=n+10m<=n+10m<=n+10
对于100%100\%100%的数据,2<=ui,vi<=n<=1000002<=u_i,v_i<=n<=1000002<=ui,vi<=n<=100000,1<=m<=2000001<=m<=2000001<=m<=200000,wi<=231w_i<=2^{31}wi<=231
保证初始图连通。
题解
题目就是求包含某条边的最小生成树。
先把原图的最小生成树求出来。
枚举图上的每一条边,考虑选择这条管道的前提下的最小花费:
如果这条边就在最小生成树上,显然,最小花费就是最小生成树的边权和。
如果这条边不在最小生成树上,如下图中的边(5,6)(5,6)(5,6):
显然如果我们加入了边(5,6)(5,6)(5,6),就会构成一个环,这个环的一部分就是(5,6)(5,6)(5,6),另一部分是在树上的555到666的路径,即5⟶3⟶4⟶65\longrightarrow3\longrightarrow4\longrightarrow65⟶3⟶4⟶6。
这样如果我们去掉环上的任意一条边,所有点还是联通的,且边权和比没去时更小。
又因为我们不能去掉边(5,6)(5,6)(5,6),所以我们只能去掉原图的最小生成树上的555到666的路径的任意一边。
且为了保证去掉这条边后边权和最小,我们要去掉这条路径上边权最大的边。
这样两种情况都讨论完了,至于第二种情况的路径上边权最大值怎么维护,可以用树剖或者倍增。
代码如下:
#include<bits/stdc++.h>#define N 1000010
#define M 2000010
#define int long long
#define ll long longusing namespace std;struct edge
{int u,v,w,id;
}e[M];int n,m,fa[N];
int f[N][20],maxn[N][20],d[N];
int cnt,head[N],nxt[N<<1],to[N<<1],w[N<<1];
ll ans,Ans[N];
bool flag[N];inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}return x*f;
}int find(int x)
{if(x==fa[x])return x;return fa[x]=find(fa[x]);
}inline bool cmp(edge a,edge b)
{return a.w<b.w;
}inline void adde(int u,int v,int wi)
{to[++cnt]=v;w[cnt]=wi;nxt[cnt]=head[u];head[u]=cnt;
}void dfs(int u)
{for(int i=1;i<=18;i++)//倍增数组{f[u][i]=f[f[u][i-1]][i-1];maxn[u][i]=max(maxn[u][i-1],maxn[f[u][i-1]][i-1]);}for(int i=head[u];i;i=nxt[i]){if(to[i]!=f[u][0]){f[to[i]][0]=u;maxn[to[i]][0]=w[i];d[to[i]]=d[u]+1;dfs(to[i]);}}
}inline int LCA(int a,int b)//a->lca->b
{int maxx=0;if(d[a]<d[b])swap(a,b);for(int i=18;i>=0;i--)if(d[f[a][i]]>=d[b]) maxx=max(maxx,maxn[a][i]),a=f[a][i];if(a==b)return maxx;for(int i=18;i>=0;i--){if(f[a][i]!=f[b][i]){maxx=max(maxx,max(maxn[a][i],maxn[b][i]));a=f[a][i],b=f[b][i];}}maxx=max(maxx,max(maxn[a][0],maxn[b][0]));return maxx;
}signed main()
{n=read(),m=read();for(register int i=1;i<=n;i++)fa[i]=i;for(register int i=1;i<=m;i++){e[i].u=read(),e[i].v=read(),e[i].w=read();e[i].id=i;}sort(e+1,e+m+1,cmp);for(register int i=1,num=0;i<=m;i++)//最小生成树{if(num==n-1)break;int a=find(e[i].u),b=find(e[i].v);if(a!=b){fa[a]=b;adde(e[i].u,e[i].v,e[i].w);adde(e[i].v,e[i].u,e[i].w);ans+=e[i].w;flag[i]=true;num++;}}d[1]=1;dfs(1);for(register int i=1;i<=m;i++){if(flag[i])//这条边在最小生成树{Ans[e[i].id]=ans;continue;}int maxx=LCA(e[i].u,e[i].v);//不在就求u、v路径上的边权最大值Ans[e[i].id]=ans-maxx+e[i].w;}for(register int i=1;i<=m;i++)printf("%lld\n",Ans[i]);return 0;
}
另,相似题:XSY2485,以及题解。
【XSY2515】管道(pipe)(最小生成树+倍增lca)相关推荐
- 【XSY2485】MST(最小生成树+倍增lca+并查集)
题面 Description 给定一个nnn个点mmm条边的连通图,保证没有自环和重边.对于每条边求出,在其他边权值不变的情况下,它能取的最大权值,使得这条边在连通图的所有最小生成树上.假如最大权值为 ...
- HDU - 3078 Network 倍增LCA
倍增lca,把路径上点全部拉出来拍个序输出第k大就过了. 不知道怎么过的,咱也不敢问. #include<stdio.h> #include<string.h> #includ ...
- BZOJ 2144 跳跳棋(神仙建模题,倍增 LCA,二分)【BZOJ修复工程】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2144 是 hydro 的 BZOJ ...
- linux操作系统进程间通信IPC之管道pipe及FIFO
linux环境下,各进程相互独立,如果想要交换两个进程之间的数据,需要通过内核,在内存中提供一个缓存区,一个进程往缓存区中写数据,一个往缓存区读数据,内核提供的这种机制称为进程间通信(IPC),常见的 ...
- 无名管道pipe使用方法
有名管道pipe函数:int pipe(int filedes[2]); 下面程序通过创建进程,父进程写入数据,子进程读取数据,从管道中读取数据. #include <stdio.h> ...
- [转]Angular2 使用管道Pipe以及自定义管道格式数据
本文转自:https://www.pocketdigi.com/20170209/1563.html 管道(Pipe)可以根据开发者的意愿将数据格式化,还可以多个管道串联. 纯管道(Pure Pipe ...
- 洛谷T1967 货车运输 Kruskal最大生成树倍增LCA
这题的题意是:对于每组x.y,求x到y路径上最小边权的最大值. 于是可以使用最大生成树,因为最大生成树满足性质:生成树中最小边权最大,且任意两点间路径上最小边权最大. 有了树之后,要求路径,那就要考虑 ...
- python 归纳 (二二)_多进程数据共享和同步_管道Pipe
# -*- coding: utf-8 -*- """ 多进程数据共享 管道Pipe逻辑:2个进程,各自发送数据到管道,对方从管道中取到数据总结:1.只适合两个进程2.r ...
- [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MB Submit: 2131 Solved: 865 [Submit][Sta ...
最新文章
- 安卓相对布局常用语句
- 首长,Redis性能优化十三条军规立好了,请过目~
- 深度学习中的激活函数总结
- 小米平板2第三方rom_【2020年1月10日更新】小米手机全系列设备代号一览
- Ubuntu18.04安装Scala
- 深入理解IIS的多线程工作机制
- 《七哥说道》第五章:入职惨做苦力,画饼一望无际
- 如何向Mac Dictionary App添加其他语言
- 当Python遇上HDF5--性能优化实战
- 财税打印机LQ 670K+ win10驱动
- 园林计算机制图在计算机上的应用,园林计算机制图
- 苹果手机页面不兼容问题——mui
- Java飞机小游戏代码详解
- AWS中IGW,NAT GW以及Egress-only IGW的概念和区别
- SQL数据修复,SQL数据库修复,SQL数据库修复软件,SQL数据库恢复,SQL数据库日志恢复软件
- [收藏]基于Spark Graphframes的社交关系图谱项目实战
- Field communityMapper in com.estate.service.impl.CommunityServiceImpl required a bean of type ‘
- (一)城市三维基础展示方案
- 计算机的工作原理是二进制原理吗,计算机是怎么通过二进制原理来工作的?
- 【板栗糖GIS】在测绘项目中——比例尺和分辨率的区别
热门文章
- 交通 流量 时间序列预测,神经网络 机器学习 BPNN
- Computer Vision_2_Active Shape Models:Active Shape Models-Their Training and Application——1995
- org.apache.solr.client.solrj.impl.CloudSolrServer$RouteException: Exception writing document id xxxx
- Linux 如何检测硬盘坏道?
- 这可能是JAVA程序员进阶架构师的最佳之路了 !
- 记忆化搜索例题 记忆化搜索
- 基于Android的社交游戏百宝箱App设计与实现
- Py西游攻关之正则表达式
- 【SpringMVC】@RequestMapping和@GetMapping的区别
- oracle报错解决