题目

给出一个无向图,问它的严格次小生成树(数据保证有解)


分析

首先先找一棵最小生成树,然后对于每条非树边\((x,y,w)\)可以找到最小生成树上\(x,y\)路径上略小于\(w\),首先如果能找到那么这条边肯定不超过\(w\),因为如果超过\(w\)肯定可以被非树边代替

但是如果上面找到的最大边等于\(w\),就不能保证严格次小了

总结一下思路,就是维护最大和次大的边,这可以通过倍增实现,在\(x,y\)跳到\(LCA\)的过程中同时可以求出最大边和次大边

先讲一下如何倍增(\(g[x][i][0/1]\)表示\(x\)跳\(2^i\)步中的最大/次大边)

\(g[x][i][0]=max(g[x][i-1][0],g[f[x][i-1]][i-1][0])\)

\(g[x][i][1]=max(g[x][i-1][0],g[f[x][i-1]][i-1][0],g[x][i-1][1],g[f[x][i-1]][i-1][1])\)

\(g[x][i][1]\)里面的是选择第二大的,优先用前面两个,前两个相等就用后两个,哪个大就拿它的下一个

这样必须保证\(g[x][i][0]>g[x][i][1]\)(代码有一点不足就是\(g[1][0][0]=g[1][0][1]\),但是貌似没有什么问题)

注意一下细节,我90分改了很久,有两个地方有小错误。在代码中会讲


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=100011;
struct rec{int x,y,w;}E[N*3]; long long sum,ans=1e16;
struct node{int y,w,next;}e[N<<1]; bool is_tree[N*3];
int bas,n,m,ls[N],fat[N],g[N][18][2],f[N][18],dep[N],k=1;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed max(int a,int b){return a>b?a:b;}
bool cmp(rec x,rec y){return x.w<y.w;}
inline signed getf(int u){return fat[u]==u?u:fat[u]=getf(fat[u]);}
inline void add(int x,int y,int w){
e[++k]=(node){y,w,ls[x]},ls[x]=k;
e[++k]=(node){x,w,ls[y]},ls[y]=k;
}
inline void Kruskal(){
rr int cnt=0;
for (rr int i=1;i<=n;++i) fat[i]=i;
for (rr int j=1;j<=m;++j){
rr int fa=getf(E[j].x),fb=getf(E[j].y);
if (fa==fb) continue;
if (fa>fb) fa^=fb,fb^=fa,fa^=fb;
fat[fa]=fb,add(E[j].x,E[j].y,E[j].w);
is_tree[j]=1,sum+=E[j].w;
if (++cnt==n-1) return;
}
}
inline void dfs(int x,int fa,int p){
dep[x]=dep[fa]+1,f[x][0]=fa,
g[x][0][0]=(p==1)?-2e9:e[p].w,g[x][0][1]=-2e9;
for (rr int i=ls[x];i;i=e[i].next)
if (e[i].y!=fa) dfs(e[i].y,x,i);
}
inline void upd(int &t1,int &t2,int z1,int z2){
if (t1<z1) t2=max(t1,z2),t1=z1;
else if (t2<z1&&t1>z1) t2=z1;
else if (t2<z2&&t1>z2) t2=z2;
//原来是只有第二行为if (t2<z1) t2=z1(一定要保证t1>t2)
//HACK数据From LOJ:(答案是800,701就是上面那种情况,oo我就不知道了)
// 9 9
// 1 2 100
// 2 3 100
// 3 4 100
// 4 5 100
// 1 6 1
// 6 7 100
// 7 8 100
// 8 9 100
// 5 9 100
}
inline signed wLCA(int x,int y,int w){
rr int t1=-2e9,t2=-2e9;
if (dep[x]<dep[y]) x^=y,y^=x,x^=y;
for (rr int i=bas;~i;--i)
if (dep[f[x][i]]>=dep[y])
upd(t1,t2,g[x][i][0],g[x][i][1]),x=f[x][i];
for (rr int i=bas;~i;--i)
if (f[x][i]!=f[y][i]){
upd(t1,t2,g[x][i][0],g[x][i][1]),
upd(t1,t2,g[y][i][0],g[y][i][1]),
x=f[x][i],y=f[y][i];
}
if (x!=y){
upd(t1,t2,g[x][0][0],g[x][0][1]),
upd(t1,t2,g[y][0][0],g[y][0][1]),
x=f[x][0],y=f[y][0];
}
if (t1==w&&t2!=-2e9) return w-t2;
else if (t1!=w&&t1!=-2e9) return w-t1;//如果t1是-2e9,那么int溢出然后就变成负数了
else return 2e9;
}
signed main(){
n=iut(); m=iut();
for (;(1<<bas)<=n;++bas);
for (rr int i=1;i<=m;++i){
rr int X=iut(),Y=iut(),W=iut();
E[i]=(rec){X,Y,W};
}
sort(E+1,E+1+m,cmp);
Kruskal(),dfs(1,0,1);
for (rr int j=1;j<=bas;++j)
for (rr int i=1;i<=n;++i){
f[i][j]=f[f[i][j-1]][j-1];
g[i][j][0]=max(g[i][j-1][0],g[f[i][j-1]][j-1][0]);
if (g[i][j-1][0]==g[f[i][j-1]][j-1][0]) g[i][j][1]=max(g[i][j-1][1],g[f[i][j-1]][j-1][1]);
else if (g[i][j-1][0]<g[f[i][j-1]][j-1][0]) g[i][j][1]=max(g[i][j-1][0],g[f[i][j-1]][j-1][1]);
else g[i][j][1]=max(g[i][j-1][1],g[f[i][j-1]][j-1][0]);
}
for (rr int i=1;i<=m;++i)
if (!is_tree[i]){
rr long long t=sum+wLCA(E[i].x,E[i].y,E[i].w);
if (ans>t) ans=t;
}
return !printf("%lld",ans);
}

#倍增,LCA,Kruskal#JZOJ 1092 洛谷 4180 [BJOI 2010] 次小生成树的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ1977或洛谷4180 [BJWC2010]次小生成树

    一道LCA+生成树 BZOJ原题链接 洛谷原题链接 细节挺多,我调了半天..累炸.. 回到正题,我们先求出随便一棵最小生成树(设边权和为\(s\)),然后扫描剩下所有边,设扫到的边的两端点为\(x,y ...

  6. 洛谷P2468 SDOI 2010 粟粟的书架

    题意:给你一个矩形书架,每个点是这本书的页数,每次询问(x1,y1)(x2,y2)这个小矩形里最少需要取几本书使得页数和等于Hi. 题解:小数据二位前缀和预处理+二分答案,大数据一行所以用主席树做,感 ...

  7. bzoj 2005 & 洛谷 P1447 [ Noi 2010 ] 能量采集 —— 容斥 / 莫比乌斯反演

    题目:bzoj 2005 https://www.lydsy.com/JudgeOnline/problem.php?id=2005   洛谷 P1447 https://www.luogu.org/ ...

  8. 洛谷.4180.[模板]次小生成树Tree(Kruskal LCA 倍增)

    题目链接 构建完MST后,枚举非树边(u,v,w),在树上u->v的路径中找一条权值最大的边(权为maxn),替换掉它 这样在 w=maxn 时显然不能满足严格次小.但是这个w可以替换掉树上严格 ...

  9. 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))

    倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...

  10. [洛谷P5190][COCI 2010] PROGRAM

    题目大意:给你$k(k\leqslant10^6)$个数,$f(x)$表示$x$的约数在$k$个数中出现的次数,在这任何数都是$0$的约数.$m(m\leqslant10^6)$次询问,每次给出$l, ...

随机推荐

  1. E4X已经被废弃,各浏览器基本上不再支持它;

    E4X是一种在ECMAScript标准的基础上加入的动态XML支持的程序语言扩展. 到2019年,目前主流浏览器已经不太支持它了,一些版本的Firefox浏览器或许还可以使用,但它已经在主流浏览器的主 ...

  2. 硬件开发笔记(八): 硬件开发基本流程,制作一个USB转RS232的模块(七):创建基础DIP元器件(晶振)封装并关联原理图元器件

    前言   有了原理图,可以设计硬件PCB,在设计PCB之间还有一个协同优先动作,就是映射封装,原理图库的元器件我们是自己设计的.为了更好的表述封装设计过程,本文描述了创建晶振封装(DIP),将原理图的 ...

  3. Html飞机大战(十五): 上线

    好家伙,   我的飞机大战部署上线了 胖虎的飞机大战 感兴趣的可以去玩一下     (怕有人接受不了这个背景,我还贴心的准备切换背景按钮,然而这并没有什么用) 现在,我们停下脚步,重新审视这个游戏   ...

  4. 【Azure Function】示例运行 python durable function(model V2)

    问题描述 参考官方文档(使用 Python 创建你的第一个持久函数:https://learn.microsoft.com/zh-cn/azure/azure-functions/durable/qu ...

  5. C++ //提高编程 模板(泛型编程 STL) //模板不可以直接使用 它只是一个框架 //模板的通用并不是万能的 //语法 //template<typename T> //函数模板两种方式 //1.自动类型推导 必须推导出一致的数据类型T,才可以使用 //2.显示指定类型 模板必须确定出T的数据类型,才可以使用

    1 //C++提高编程 模板(泛型编程 STL) 2 //模板不可以直接使用 它只是一个框架 3 //模板的通用并不是万能的 4 //语法 5 //template<typename T> ...

  6. CSV转Excel,命中关键词标红

    CSV转Excel,命中关键词标红 package com.wenwo.schedule.job.mainJob; import java.io.ByteArrayOutputStream; impo ...

  7. css移动端开发

    ​ 移动端浏览器主要对webkit内核兼容,现在的移动端主要针对手机端开发,移动端碎片化比较严重,分辨率和屏幕尺寸不一 调试方法 谷歌浏览器模拟手机调试 搭建本地web服务器,手机和服务器在同一个局域 ...

  8. Spring事务(一)-事务配置

    事务是数据库操作最基本的单元,是逻辑上的一组操作,这一组操作在同一个会话中要么都执行成功,要么都失败,这也是事务的最基本特性--原子性.事务的作用是为了保证系统数据的正确性,因此,数据库应用程序中是会 ...

  9. HTML(html结构、标签导读 、路径))

    HTML第一天 我们接下来是进行的网页开发网页的相关概念: 什么是网页? 什么是HTML? 网页的形成? 一 什么是网页: 1.网站是指在因特网上根据一定的规则,使用 HTML 等制作的用于展示特定内 ...

  10. 记录--为什么没有人能讲清楚 BFC?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.你看得懂权威的解释吗? 1. CSS 规范中对 BFC 的描述 CSS 规范(英文) | 中文翻译 浮动,绝对定位的元素,非块盒的块容 ...