P4180 [BJWC2010]严格次小生成树

P4180

题意

求出一个无向联通图的严格次小生成树。严格次小生成树的定义为边权和大于最小生成树的边权和但不存在另一棵生成树的边权和在最小生成树和严格次小生成树之间(不相等)。

思路

先求出一颗最小生成树,发现严格次小生成树一定是其断了一条边并加了一条边且边权和的增加量最小。

那么我们继续在最小生成树上做。对于每一条不是最小生成树上的边,求出其两端两点间在最小生成树上路径上的边的最大值。然鹅,如果用倍增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]严格次小生成树的更多相关文章

  1. 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)

    洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...

  2. [BJWC2010]严格次小生成树(LCA,最小生成树)

    [BJWC2010]严格次小生成树 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图 ...

  3. 洛谷 P4180 【模板】严格次小生成树[BJWC2010]【次小生成树】

    严格次小生成树模板 算法流程: 先用克鲁斯卡尔求最小生成树,然后给这个最小生成树树剖一下,维护边权转点权,维护最大值和严格次大值. 然后枚举没有被选入最小生成树的边,在最小生成树上查一下这条边的两端点 ...

  4. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  5. [BJWC2010] 严格次小生成树

    [BJWC2010]严格次小生成树算法及模板 所谓次小生成树,即边权之和第二小的生成树,但所谓严格,就是不能和最小的那个相等. 求解严格次小生成树的方法一般有倍增和LCT两种.当然LCT那么高级的我当 ...

  6. 【洛谷P4180】严格次小生成树

    题目大意:给定一个 N 个顶点,M 条边的带权无向图,求该无向图的一个严格次小生成树. 引理:有至少一个严格次小生成树,和最小生成树之间只有一条边的差异. 题解: 通过引理可以想到一个暴力,即:先求出 ...

  7. 洛谷P4180 [Beijing2010组队]次小生成树Tree

    题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...

  8. BZOJ1977/LuoguP4180【模板】严格次小生成树[BJWC2010] (次小生成树)

    这道题本身思维难度不大,但综合性强,细节多 在其上浪一个早上,你的 最小生成树 树链剖分 线段树 DEBUG能力... 都大幅提升 细节与思路都在代码里面了. 欢迎hack. #include< ...

  9. [Luogu] 次小生成树

    https://www.luogu.org/problemnew/show/P4180#sub 严格次小生成树,即不等于最小生成树中的边权之和最小的生成树 首先求出最小生成树,然后枚举所有不在最小生成 ...

随机推荐

  1. Python小白的数学建模课-07 选址问题

    选址问题是要选择设施位置使目标达到最优,是数模竞赛中的常见题型. 小白不一定要掌握所有的选址问题,但要能判断是哪一类问题,用哪个模型. 进一步学习 PuLP工具包中处理复杂问题的字典格式快捷建模方法. ...

  2. OpenCV开发实战1——抖音哈哈镜效果

    前言 在抖音中,我们经常看到各种抖音玩家都喜欢使用哈哈镜效果.那么什么是哈哈镜呢? 在现实生活中,哈哈镜是指一种表面凹凸不平的镜子,可以反应出人像及物体的扭曲面貌.简单点来说就是拉伸人脸(物件),或者 ...

  3. 使用 Docker 部署 Node 应用

    容器将应用与环境打包整合,解决了应用外部依赖的痛点,打包后通过窗口可方便地部署到任意环境,用过就知道很香. 创建示例应用 以 NestJS 为例,先创建一个示例应用. $ npm i -g @nest ...

  4. 消息队列面试题、RabbitMQ面试题、Kafka面试题、RocketMQ面试题 (史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  5. 无需会员将有道云笔记脑图转换xmind

    我的烦恼 有道云笔记有脑图功能,我平时经常用到,之所以很少用到其他脑图工具,是因为我一直用有道云笔记写笔记.因此编辑脑图和查看脑图比较方便,但是需要将脑图导出的时候目前只支持图片和xmind,但是需要 ...

  6. C#设计模式学习之装饰者模式

    写这个随笔时,其实对该模式理解的并不是十分透彻.在此想到什么写什么,希望对自己对他人有所帮助. 装饰者模式主要是应用继承和组合的思想,极大的实现了程序的多态,使得的程序有了更高的扩展性. 第一个基础例 ...

  7. Vue(8)列表渲染v-for

    循环 在模板中可以用v-for指令来循环数组,对象等. 循环数组 我们可以用 v-for 指令基于一个数组来渲染一个列表.v-for 指令需要使用 item in items形式的特殊语法,其中 it ...

  8. github push pull error port 443: Timed out

    最近github只有开代理才能打开,但是即使能打开,进行push或者pull会经常报类似error port 443: Timed out的错误,网上搜了很久才找到解决办法. 首先要查询当前本机使用的 ...

  9. Docker 镜像针对不同语言的精简策略

    导航: 这里分为几个部分. 相关转载云原生:米开朗基杨 1.Docker减小镜像体积 2.Docker镜像针对不同语言的精简策略 对于刚接触容器的人来说,他们很容易被自己制作的 Docker 镜像体积 ...

  10. 关于Ubuntu开启ifConfig和Ping命令的支持,查看本机Ip地址和检查外部连接

    背景介绍 我们都知道Windows中自带了对ipconfig和ping的命令支持,但是在Linux中可能是默认没有带这个支持的. 那么接下来,我们介绍如何在Linux中,安装相关组件来支持Linux版 ...