【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集
【题意】给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它。n,m<=2*10^5,1<=wi<=10^9。
【算法】最小生成树+倍增LCA+并查集
【题解】首先求出图的一个最小生成树M,则所有边分成树边和非树边。
一、对于非树边(u,v),假设u和v在最小生成树M上的路径的最大边权是Max。要保证这条边在最小生成树上,只要w(u,v)=Max-1。
下面证明w(u,v)=Max-1时,一定在任意最小生成树上。
证明:假设另一个最小生成树OM不包含(u,v),那么u和v在最小生成树OM上的路径的所有边权<=Max-1,按照kruscal算法从小到大加边的情况,(u,v)一定会被最小生成树OM首先连通,故M不是最小生成树,矛盾。
二、对于树边(u,v),假设所有在最小生成树M上的路径经过它的非树边的最小边权是Min。要保证这条边在最小生成树M上(不会被替换),只要w(u,v)=Min-1。
证明:如果(u,v)已经是所有它所在的环中的最小边,那么一定会先被连通。
最后,我们需要解决问题是:找到一个最小生成树,对于每条非树边找到路径最大值,然后给路径贡献最小值标记,最后统计树边的答案。
这用树链剖分+线段树是很容易实现的,还可以用线段树合并(权值),不过最简便的是倍增+并查集。
倍增:记录路径最大值,即可回答第一个询问。
并查集:非树边从小到大排序后依次处理,标记到的边就是最小值了,处理完后用并查集并起来以后不再处理(初始fa[i]=i),即每个点的父亲指向祖先中最近的未处理点(边),类似安全路经Travel。
注意先kruscal后按照生成树边来dfs建树。答案可能有0。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct edge{int id,u,v,w,from;}e[maxn*],ed[maxn*];
int n,m,first[maxn],tot,f[maxn][],g[maxn][],deep[maxn],fa[maxn],a[maxn],E[maxn],ans[maxn];
void insert(int u,int v,int w,int id){tot++;e[tot].id=id;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
bool cmp(edge a,edge b){return a.w<b.w||(a.w==b.w&&a.id<b.id);}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void dfs(int x,int fa){
for(int i=;(<<i)<=deep[x];i++){
f[x][i]=f[f[x][i-]][i-];
g[x][i]=max(g[x][i-],g[f[x][i-]][i-]);
}
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&a[e[i].id]){
deep[e[i].v]=deep[x]+;
f[e[i].v][]=x;
g[e[i].v][]=e[i].w;
E[e[i].v]=e[i].id;
dfs(e[i].v,x);
}
}
int lca(int x,int y){
if(deep[x]<deep[y])swap(x,y);
int ans=,d=deep[x]-deep[y];
for(int i=;i<=;i++)if(d&(<<i))ans=max(ans,g[x][i]),x=f[x][i];
if(x==y)return ans;
for(int i=;i>=;i--)if((<<i)<=deep[x]&&f[x][i]!=f[y][i]){
ans=max(ans,max(g[x][i],g[y][i]));
x=f[x][i];y=f[y][i];
}
return max(ans,max(g[x][],g[y][]));
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].w);//
ed[i].id=i;
}
sort(ed+,ed+m+,cmp);
for(int i=;i<=n;i++)fa[i]=i;
for(int i=;i<=m;i++){
int x=find(ed[i].u),y=find(ed[i].v);
if(x!=y){a[ed[i].id]=;fa[x]=y;}
}
for(int i=;i<=m;i++)insert(ed[i].u,ed[i].v,ed[i].w,ed[i].id),insert(ed[i].v,ed[i].u,ed[i].w,ed[i].id);
dfs(,);
for(int i=;i<=n;i++)fa[i]=i;
memset(ans,-,sizeof(ans));//
for(int i=;i<=m;i++)if(!a[ed[i].id]){
int x=find(ed[i].u),y=find(ed[i].v);
ans[ed[i].id]=lca(ed[i].u,ed[i].v)-;
while(x!=y){
if(deep[x]<deep[y])swap(x,y);
ans[E[x]]=ed[i].w-;
x=fa[x]=find(f[x][]);//
}
}
for(int i=;i<=m;i++)printf("%d ",ans[i]);
return ;
}
【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集的更多相关文章
- cf827D Best Edge Weight (kruskal+倍增lca+并查集)
先用kruskal处理出一个最小生成树 对于非树边,倍增找出两端点间的最大边权-1就是答案 对于树边,如果它能被替代,就要有一条非树边,两端点在树上的路径覆盖了这条树边,而且边权不大于这条树边 这里可 ...
- 【BZOJ-3910】火车 倍增LCA + 并查集
3910: 火车 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 262 Solved: 90[Submit][Status][Discuss] De ...
- 训练指南 UVA - 11354(最小生成树 + 倍增LCA)
layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true ma ...
- 【bzoj3732】Network 最小生成树+倍增LCA
题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...
- 【bzoj4242】水壶 BFS+最小生成树+倍增LCA
题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入 ...
- BZOJ 3732 Network —— 最小生成树 + 倍增LCA
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 <= N <= 15, ...
- BFS+最小生成树+倍增+LCA【bzoj】4242 水壶
[bzoj4242 水壶] Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有 ...
- 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)
传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...
- Codeforces Round #363 (Div. 2) D. Fix a Tree —— 并查集
题目链接:http://codeforces.com/contest/699/problem/D D. Fix a Tree time limit per test 2 seconds memory ...
随机推荐
- python处理时间相关的方法(汇总)
记录python处理时间的模块:time模块.datetime模块和calendar模块. python版本:2.7 在介绍模块之前,先说下以下几点: 1.时间通常有这几种表示方式: a.时间戳:通常 ...
- inotify 工具 是一种强大的、细粒度的、异步文件系统监控机制
前言:Inotify是一种强大的.细粒度的.异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性.读写属性.权限属性.删除创建.移动等操作,也就是可以监控文件发生的一切变化. ...
- C语言文法推导
- 201621123037 《Java程序设计》第7周学习总结
作业06-接口.内部类 1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 答: 思维导图: 其他-笔记: 2. 书面作业 1. ArrayList代码分析 1.1 解释Arr ...
- 欧拉函数phic以及超大数的快速幂
题目:求a^b*c%mod; 其中b<=10^100000; 是不是很大..... /*当你要计算 A^B%C的时候 因为此题中的B很大,达到10^100000,所以我们应该联想到降幂公式. 降 ...
- application/x-www-form-urlencoded 与 application/json区别
两种请求方式对服务器端都没什么影响 application/x-www-form-urlencoded方式是比较老的一种方式,这种方式的好处就是浏览器都支持, 在请求发送过程中会对数据进行序列化处理, ...
- 平衡树以及AVL树
平衡树是计算机科学中的一类数据结构. 平衡树是计算机科学中的一类改进的二叉查找树.一般的二叉查找树的查询复杂度是跟目标结点到树根的距离(即深度)有关,因此当结点的深度普遍较大时,查询的均摊复杂度会上升 ...
- 【uoj#175】新年的网警 结论题+Hash
题目描述 给出一张 $n$ 个点 $m$ 条边的无向连通图,每条边的边权为1.对于每个点 $i$ ,问是否存在另一个点 $j$ ,使得对于任意一个不为 $i$ 或 $j$ 的点 $k$ ,$i$ 到 ...
- 洛谷 P2664 树上游戏 解题报告
P2664 树上游戏 题目描述 \(\text{lrb}\)有一棵树,树的每个节点有个颜色.给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量.以及 ...
- 洛谷p1017 进制转换(2000noip提高组)
洛谷P1017 进制转换 题意分析 给出一个数n,要求用负R进制显示. n∈[-32768,32767].R ∈[-20,-2] 考察的是负进制数的转换,需要理解短除法. 看到这道题的时候,我是比较蒙 ...