严格次小生成树
首先看看如果不严格我们怎么办。
由此,我们发现一个结论,求非严格次小生成树,只需要先用kruskal算法求得最小生成树,然后暴力枚举非树边,替换路径最大边即可。
那要是严格呢?
我们发现如果是严格的次小生成树,那么将一条边替换另一条时,这两条边的权值一定不相同
但是,我们知道,替换边肯定大于等于被替换边(因为如果替换边小于被替换边,就存在一颗包含替换边而不包含被替换边的一棵权值更小的生成树,原树就不是最小生成树了)
所以替换边要么等于路径上最大的边,要么比最大的边还大。
利用这个性质,我们只需要维护路径中的最大值和次大值,当替换边等于路径上的最大值,我们直接换用严格次大值即可。
一些细节
1.我维护两点之间路径最大值用的是LCT,但是正解是LCA。LCT必须要开O2才能跑过去。
2.数组要开足够大,最后统计答案时要开long long,不然会爆int
我的代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define rg register int
#define ll long long
#define RG register
#define il inline
using namespace std;
il ll gi() {
RG ll x=0;rg o=0;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||'9'<ch)) ch=getchar();
if(ch=='-') o=1,ch=getchar();
while('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return o?-x:x;
}
int n,m;
#define SZ 7000010
struct Edge {int a,b;ll w;}e[SZ];
bool cmp(Edge a,Edge b) {return a.w<b.w;}
#define lson tr[x].ch[0]
#define rson tr[x].ch[1]
struct Splaytree{int fa,ch[2],rev,mxp,mxp2;}tr[SZ];
il void pushup(rg x)
{
tr[x].mxp=x; tr[x].mxp2=0;
if(e[tr[lson].mxp].w>e[tr[x].mxp].w) tr[x].mxp=tr[lson].mxp;
if(e[tr[rson].mxp].w>e[tr[x].mxp].w) tr[x].mxp=tr[rson].mxp;
// 维护 最大
if(e[tr[lson].mxp].w!=e[tr[x].mxp].w && (e[tr[lson].mxp].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[lson].mxp;
if(e[tr[lson].mxp2].w!=e[tr[x].mxp].w && (e[tr[lson].mxp2].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[lson].mxp2;
if(e[tr[rson].mxp].w!=e[tr[x].mxp].w && (e[tr[rson].mxp].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[rson].mxp;
if(e[tr[rson].mxp2].w!=e[tr[x].mxp].w && (e[tr[rson].mxp2].w>e[tr[x].mxp].w||!tr[x].mxp2) ) tr[x].mxp2=tr[rson].mxp2;
// 维护严格次大
}
il void pushdown(rg x)
{
if(tr[x].rev)
{
tr[lson].rev^=1,tr[rson].rev^=1;
swap(lson,rson),tr[x].rev=0;
}
}
il bool isroot(rg x)
{
return tr[tr[x].fa].ch[0]!=x && tr[tr[x].fa].ch[1]!=x;
}
il void rotate(rg x)
{
rg y=tr[x].fa,z=tr[y].fa;
rg k=tr[y].ch[1]==x;
if(!isroot(y)) tr[z].ch[y==tr[z].ch[1]]=x;tr[x].fa=z;
tr[y].ch[k]=tr[x].ch[k^1],tr[tr[x].ch[k^1]].fa=y;
tr[x].ch[k^1]=y,tr[y].fa=x;
pushup(y),pushup(x);
}
int stk[SZ],top;
il void splay(rg x)
{
stk[top=1]=x;
for(rg i=x;!isroot(i);i=tr[i].fa) stk[++top]=tr[i].fa;
for(;top;--top) pushdown(stk[top]);
while(!isroot(x))
{
rg y=tr[x].fa,z=tr[y].fa;
if(!isroot(y))
(tr[y].ch[0]==x)^(tr[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
}
il void access(rg x) {for(rg y=0;x;y=x,x=tr[x].fa)splay(x),rson=y,pushup(x);}
il void makeroot(rg x) {access(x);splay(x);tr[x].rev^=1;}
il int findroot(rg x) {access(x);splay(x);while(lson) x=lson;return x;}
il void split(rg x,rg y) {makeroot(x);access(y);splay(y);}
il int query(rg x,rg y) {split(x,y);return tr[y].mxp;} //求x 到 y最大值
il int query2(rg x,rg y) {split(x,y);return tr[y].mxp2;} // 求x 到 y严格次大值
il void link(rg x,rg y) {makeroot(x);tr[x].fa=y;}
il void cut(rg x,rg y) {split(x,y);if(tr[y].ch[0]==x)tr[y].ch[0]=tr[x].fa=0;}
int fa[SZ];int find_fa(rg x) {if(x!=fa[x]) fa[x]=find_fa(fa[x]);return fa[x];} //一行并查集
bool check[SZ];
int main()
{
n=gi(),m=gi();
for(rg i=1;i<=m;++i) e[i]=(Edge){gi(),gi(),gi()};
// 先求一遍最小生成树 ans 记录最小生成树边的大小
RG ll ans=0;
sort(e+1,e+1+m,cmp);
for(rg i=1;i<=n;++i) fa[i]=i; // 初始化并查集
for(rg f1,f2,i=1;i<=m;++i)
{
f1=find_fa(e[i].a);
f2=find_fa(e[i].b);
if(f1!=f2)
{
check[i]=1; // check=1 表示最小生成树中有这一条边 反之
fa[f1]=f2;
ans+=e[i].w;
link(e[i].a+m,i);
link(e[i].b+m,i);
}
}
#define INF 2147483647
#define Getmin(a,b) (a)=(a)>(b)?(b):(a)
RG ll Ans=INF;
for(rg f1,f2,i=1;i<=m;++i)
{
if(check[i]) continue; //我们选择不再最小生成树上的边
rg mxp=query(e[i].a+m,e[i].b+m);
if(e[mxp].w==e[i].w)
{
rg mxp2=query2(e[i].a+m,e[i].b+m);
if(!mxp2 || e[mxp2].w==e[mxp].w) continue;
Getmin(Ans,e[i].w-e[mxp2].w);
}
else Getmin(Ans,e[i].w-e[mxp].w);
}
cout<<ans+Ans;
return 0;
}
(luogu4180) [Beijing2010组队]次小生成树Tree的更多相关文章
-
BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
-
1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
-
【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
[BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...
-
[BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 5168 Solved: 1668[S ...
-
洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
-
【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
-
BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树
描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...
-
【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
-
【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并
题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...
随机推荐
-
Msyql-检测数据库版本
show variables like '%version%'; 数据库版本结果: "protocol_version","" "version&qu ...
-
bzoj1124[POI2008]枪战maf
这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是 ...
-
java Exchanger 2
//Listing 6-3. Using an Exchanger to Swap Buffers import java.util.ArrayList; import java.util.List; ...
-
WPF 数据绑定
1.1绑定到对象 1.1.1.前台绑定 前台代码 5: </Grid> 1: <Grid x:Name=”GridProductDetails”> 2: 3: <Te ...
-
Jersey(1.19.1) - Hello World, Get started with Jersey using the embedded Grizzly server
Maven Dependencies The following Maven dependencies need to be added to the pom: <dependency> ...
-
解决ListView异步加载图片错乱问题 .
发一个异步图片加载控件.网上也有大把的异步网络加载图片的控件,但是有一个问题,异步加载会造成列表中的图片混乱,因为列表的每一项的View都可能被重用,异步加载的时候多个异步线程引用到了同一个View将 ...
-
view添加阴影无效
需求:需要给cell里的imageview添加阴影 问题:按照标准的代码添加阴影,然并卵:代码如下: imageview.layer.shadowColor = [[UIColor blackColo ...
-
Java log4j使用
log4j下载地址: http://logging.apache.org/log4j/1.2/download.html 本人用的是log4j-1.2.17.jar的jar包. 接下来我们配置下一lo ...
-
mongo分布式集群搭建手记
一.架构简介 目标 单机搭建mongodb分布式集群(副本集 + 分片集群),演示mongodb分布式集群的安装部署.简单操作. 说明 在同一个vm启动由两个分片组成的分布式集群,每个分片都是一个PS ...
-
Linux内核d_path函数应用的经验总结
问题背景 一个内核模块中,需要通过d_path接口获取文件的路径,然后与目标文件白名单做匹配. 在生产环境中,获取的文件是存在的,但是与文件白名单中的文件总是匹配失败. 问题定位: 通过打印d_pat ...