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应用_读取Excel数据【二】_二次封装之函数式封装

    目的:想要把对Excel文件读取做成一个通用的函数式封装,便于后续简单调用,隔离复杂性. 未二次封装前原代码: #coding=gbkimport osimport xlrdcurrent_path= ...

  2. Spring IOC(控制反转)思想笔记

    Spring IOC(控制反转)思想笔记 IOC控制反转基本理念就是将程序控制权从程序员手中交给用户自定义,从而避免了因为用户一个小需求的变化使得程序员需要改动大量代码. 案例 如果按照之前javaw ...

  3. 20个提高开发效率的JavaScript技巧

    减少代码行数和加快开发的技术! 我们在开发中,经常要写一些函数,如排序.搜索.寻找唯一的值.传递参数.交换值等,在这里我列出了我搜集的一些技术资源,可以像高手一样写出这些函数! JavaScript确 ...

  4. CentOS 6.x 安装图形界面

    CentOS 6.x 安装图形界面一.首先查看系统的运行级别以及是否安装了桌面环境1.使用命令 runlevel 查看当前系统运行级别[root@42 ~]# runlevelN 32.使用命令 yu ...

  5. k8s-记一次安全软件导致镜像加载失败

    近期在现场项目中遇到了一个镜像加载失败的问题,相关报错如下: Error processing tar file(exit status 1): symlink . /usr/bin/X11: per ...

  6. 带你从头到尾捋一遍MySQL索引结构

    索性这次把数据库中最核心的也是最难搞懂的内容,也就是索引,分享给大家. 这篇博客我会谈谈对于索引结构我自己的看法,以及分享如何从零开始一层一层向上最终理解索引结构. 从一个简单的表开始 create ...

  7. 『言善信』Fiddler工具 — 16、使用Fiddler抓取移动端App请求

    目录 1.抓取Android移动端App请求 2.抓取IOS移动端App请求 3.总结: 1.抓取Android移动端App请求 前提: 因为Fiddler抓包的原理就是通过代理,所以确保被测终端要和 ...

  8. 题解 P3605 [USACO17JAN]Promotion Counting P

    分块\(yyds\) ----关于线段树合并的题我用分块过掉这件事 题目传送门 先说正解 正解当然是线段树合并等一类做法了 至于解析...出门右转题解区第一篇 (就是他让我看不懂,然后用分块打的\(Q ...

  9. Golang通过反射拼接一个结构体所有字段

    golang通过反射拼接一个结构体所有字段 需求 将一个结构体所有字段以"|"连接拼接成字符串 golang 不同类型拼接成string使用Sprintf比较麻烦,如果一个结构体有 ...

  10. 1.QT多线程使用小结

    开头 一个进程可以有一个或更多线程同时运行.线程可以看做是"轻量级进程",进程完全由操作系统管理,线程即可以由操作系统管理,也可以由应用程序管理. Qt 使用QThread来管理线 ...