P4180 [BJWC2010]严格次小生成树
P4180 [BJWC2010]严格次小生成树
题意
求出一个无向联通图的严格次小生成树。严格次小生成树的定义为边权和大于最小生成树的边权和但不存在另一棵生成树的边权和在最小生成树和严格次小生成树之间(不相等)。
思路
先求出一颗最小生成树,发现严格次小生成树一定是其断了一条边并加了一条边且边权和的增加量最小。
那么我们继续在最小生成树上做。对于每一条不是最小生成树上的边,求出其两端两点间在最小生成树上路径上的边的最大值。然鹅,如果用倍增LCA找,发现如果求出来的最大值与该边权值相等,那么得出的答案就是不合法的。所以我们还必须维护一个倍增范围内严格次小边权。
然后找到最小的值输出就行啦!
对于维护严格次小的值,我认为可以先求出最大值,然后比较找出与最大值不等的最大值就是次大值。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#define int long long
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=1e5+10,maxm=3e5+10,INF=0x3f3f3f3f3f3f3f3f;
int n,m;
struct Edge{
int u,v,dis;
bool is;
inline bool operator <(const Edge &zp)const {return dis<zp.dis;}
}e[maxm];
int ecnt,head[maxn],to[maxn<<1],Fa[maxn],nxt[maxn<<1],v[maxn<<1],ans=INF,sum,fa[maxn][25],mx[maxn][25],pmx[maxn][25],dep[maxn];
inline int find(int x){return Fa[x]==x?x:Fa[x]=find(Fa[x]);}
inline void addedge(int a,int b,int c){
to[++ecnt]=b,nxt[ecnt]=head[a],head[a]=ecnt,v[ecnt]=c;
to[++ecnt]=a,nxt[ecnt]=head[b],head[b]=ecnt,v[ecnt]=c;
}
inline void kruskal(){
for(int i=1;i<=n;i++)Fa[i]=i;
sort(e+1,e+1+m);
int cnt=0;
for(int i=1;i<=m;i++){
int fx=find(e[i].u),fy=find(e[i].v);
if(fx!=fy){
Fa[fx]=fy;
addedge(e[i].u,e[i].v,e[i].dis);
e[i].is=1;
sum+=e[i].dis;
if(++cnt==n-1)break;
}
}
}
void dfs(int x,int f){
fa[x][0]=f;
dep[x]=dep[f]+1;
for(int i=0;i<=20;i++){
fa[x][i+1]=fa[fa[x][i]][i];
mx[x][i+1]=max(mx[x][i],mx[fa[x][i]][i]);
if(mx[x][i+1]!=mx[x][i])pmx[x][i+1]=max(pmx[x][i+1],mx[x][i]);
if(mx[x][i+1]!=mx[fa[x][i]][i])pmx[x][i+1]=max(pmx[x][i+1],mx[fa[x][i]][i]);
if(mx[x][i+1]!=pmx[x][i])pmx[x][i+1]=max(pmx[x][i+1],pmx[x][i]);
if(mx[x][i+1]!=pmx[fa[x][i]][i])pmx[x][i+1]=max(pmx[x][i+1],pmx[fa[x][i]][i]);
}
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(u==f)continue;
mx[u][0]=v[i];
dfs(u,x);
}
}
inline void LCA(int x,int y,int &mxx,const int &MX){
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i+1;i--)if(dep[fa[x][i]]>=dep[y]){
if(mx[x][i]!=MX)mxx=max(mxx,mx[x][i]);
else mxx=max(mxx,pmx[x][i]);
x=fa[x][i];
}
if(x==y)return;
for(int i=20;i+1;i--)if(fa[x][i]!=fa[y][i]){
if(mx[x][i]!=MX)mxx=max(mxx,mx[x][i]);
else mxx=max(mxx,pmx[x][i]);
x=fa[x][i];
if(mx[y][i]!=MX)mxx=max(mxx,mx[y][i]);
else mxx=max(mxx,pmx[y][i]);
y=fa[y][i];
}
if(mx[x][0]!=MX)mxx=max(mxx,mx[x][0]);
else mxx=max(mxx,pmx[x][0]);
if(mx[y][0]!=MX)mxx=max(mxx,mx[y][0]);
else mxx=max(mxx,pmx[y][0]);
}
inline void work(){
n=read(),m=read();
for(int i=1;i<=m;i++)e[i].u=read(),e[i].v=read(),e[i].dis=read();
kruskal();
dfs(1,0);
for(int i=1;i<=m;i++)if(!e[i].is){
int x=e[i].u,y=e[i].v,MX=-INF;
LCA(x,y,MX,e[i].dis);
ans=min(ans,sum-MX+e[i].dis);
}
printf("%lld",ans);
}
}
signed main(){
star::work();
return 0;
}
P4180 [BJWC2010]严格次小生成树的更多相关文章
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
- [BJWC2010]严格次小生成树(LCA,最小生成树)
[BJWC2010]严格次小生成树 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图 ...
- 洛谷 P4180 【模板】严格次小生成树[BJWC2010]【次小生成树】
严格次小生成树模板 算法流程: 先用克鲁斯卡尔求最小生成树,然后给这个最小生成树树剖一下,维护边权转点权,维护最大值和严格次大值. 然后枚举没有被选入最小生成树的边,在最小生成树上查一下这条边的两端点 ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- [BJWC2010] 严格次小生成树
[BJWC2010]严格次小生成树算法及模板 所谓次小生成树,即边权之和第二小的生成树,但所谓严格,就是不能和最小的那个相等. 求解严格次小生成树的方法一般有倍增和LCT两种.当然LCT那么高级的我当 ...
- 【洛谷P4180】严格次小生成树
题目大意:给定一个 N 个顶点,M 条边的带权无向图,求该无向图的一个严格次小生成树. 引理:有至少一个严格次小生成树,和最小生成树之间只有一条边的差异. 题解: 通过引理可以想到一个暴力,即:先求出 ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree
题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...
- BZOJ1977/LuoguP4180【模板】严格次小生成树[BJWC2010] (次小生成树)
这道题本身思维难度不大,但综合性强,细节多 在其上浪一个早上,你的 最小生成树 树链剖分 线段树 DEBUG能力... 都大幅提升 细节与思路都在代码里面了. 欢迎hack. #include< ...
- [Luogu] 次小生成树
https://www.luogu.org/problemnew/show/P4180#sub 严格次小生成树,即不等于最小生成树中的边权之和最小的生成树 首先求出最小生成树,然后枚举所有不在最小生成 ...
随机推荐
- Java 将PPT幻灯片转为HTML
本文以Java程序代码为例展示如何通过格式转换的方式将PPT幻灯片文档转为HTML文件.这里的PPT幻灯片可以是.ppt/.pptx/.pps/.ppsx/.potx等格式. 代码实现思路:[加载PP ...
- 28.qt quick-ListView高仿微信好友列表和聊天列表
1.视图模型介绍 在Qml中.常见的View视图有: ListView: 列表视图,视图中数据来自ListModel.XmlListModel或c++中继承自QAbstractItemModel或Q ...
- 【CMD】修改文件夹的属性
将 d:\文件夹 添加 只读 属性: attrib +r d:\文件夹 /d 将 d:\文件夹 去掉 只读 属性: attrib -r d:\文件夹 /d 其他属性可以参考帮助文件:
- Golang Heap 源码剖析
堆原理解析 堆一般指二叉堆.是使用完全二叉树这种数据结构构建的一种实际应用.通过它的特性,分为最大堆和最小堆两种. 如上图可知,最小堆就是在这颗二叉树中,任何一个节点的值比其所在子树的任意一个节点都要 ...
- Nginx为什么快到根本停不下来?
Nginx 是一个免费的,开源的,高性能的 HTTP 服务器和反向代理,以及 IMAP / POP3 代理服务器. 图片来自 Pexels Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资 ...
- ST算法模板
void work() { int t=log(n)/log(2); for(int j=1;j<=t;++j) { for(int i=1;i<=(n+1-(1<<j));+ ...
- Pandas高级教程之:处理text数据
目录 简介 创建text的DF String 的方法 columns的String操作 分割和替换String String的连接 使用 .str来index extract extractall c ...
- 【.NET 与树莓派】TM1638 模块的按键扫描
上一篇水文中,老周马马虎虎地介绍 TM1638 的数码管驱动,这个模块除了驱动 LED 数码管,还有一个功能:按键扫描.记得前面的水文中老周写过一个 16 个按键的模块.那个是我们自己写代码去完成键扫 ...
- 信息熵,交叉熵与KL散度
一.信息熵 若一个离散随机变量 \(X\) 的可能取值为 \(X = \{ x_{1}, x_{2},...,x_{n}\}\),且对应的概率为: \[p(x_{i}) = p(X=x_{i}) \] ...
- 使用pdb进行Python调试
调试应用有时是一个不受欢迎的工作,当你长期编码之后,只希望写的代码顺利运行.但是,很多情况下,我们需要学习一个新的语言功能或者实验检测新的方法,从而去理解其中运行的机制原理. 即使不考虑这样的场景,调 ...