luogu 4180 严格次小生成树
次小生成树,顾名思义和次短路的思路似乎很类似呀,
于是就先写了个kruskal(prim不会)跑出最小生成树,给所有路径打标记,再逐个跑最小生成树取大于最小生成树的最小值 50分
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define dec(i,x,y) for(register int i=x;i>=y;i--)
#define ll long long
using namespace std;
const int N=;
const int M=;
const int inf=0x3f3f3f3f;
inline int read(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;}
int n,m,u,v,w,fa[N],ok[N],k;
struct node{int u,v,w;}e[M<<];
bool cmp(node a,node b){return a.w<b.w;}
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int kruskal(){
int cnt=n,ans=;
rep(i,,n) fa[i]=i;
for(int i=;i<=m;i++){
if(cnt==) break;
if(ok[i]==){
int xx=find(e[i].u),yy=find(e[i].v);
if(xx!=yy) fa[yy]=xx,cnt--,ans+=e[i].w;}
}return ans;}
int main(){
n=read();m=read();
rep(i,,m){
u=read();v=read();w=read();
e[i]=(node){u,v,w};} sort(e+,e++m,cmp);
//ok =0代表
int ans=inf,mi=kruskal();
for(int i=;i<=m;i++){
ok[i]=;k=kruskal();
if(k>mi) ans=min(ans,k);ok[i]=;}
printf("%d\n",ans);
return ;
}
100分(啥时候得再复习一下,不看题解不会做系列,ganxiehzwercode,啥时候再拿出来重新写一写)
对于非最小生成树上的路径,其u,v加入后(可能)形成一个环,分别从u.v到lca寻找最大及次大路径,若最大路径不等于(其实就是小于)非生成树边,记录这个最小增量,
相等则取次小边,防止出现 次小==最小
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define N 100001
#define M 300001
#define inf 0x7fffffff
#define ll long long
using namespace std;
int n,m,tot,cnt,mn=inf;ll ans;
int f[N],head[N],dep[N],fa[N][],d1[N][],d2[N][];
struct data{int x,y,v;bool sel;}a[M];
struct edge{int to,next,v;}e[N<<];
bool cmp(data a,data b){return a.v<b.v;}
void insert(int u,int v,int w){
e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;
e[++cnt].to=u;e[cnt].next=head[v];e[cnt].v=w;head[v]=cnt;}
inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void dfs(int u,int f){
for(int i=;i<=;i++){
if(dep[u]<(<<i))break;
fa[u][i]=fa[fa[u][i-]][i-];
d1[u][i]=max(d1[u][i-],d1[fa[u][i-]][i-]);
if(d1[u][i-]==d1[fa[u][i-]][i-])
d2[u][i]=max(d2[u][i-],d2[fa[u][i-]][i-]);
else d2[u][i]=min(d1[u][i-],d1[fa[u][i-]][i-]),
d2[u][i]=max(d2[u][i],max(d2[u][i-],d2[fa[u][i-]][i-]));
}for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==f) continue;
fa[v][]=u;
d1[v][]=e[i].v;
dep[v]=dep[u]+;
dfs(v,u);
}
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int t=dep[x]-dep[y];
for(int i=;i<=;i++)
if((<<i)&t)x=fa[x][i];
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i]; if(x==y)return x;
return fa[x][];}
void cal(int x,int f,int v){
int mx1=,mx2=;
int t=dep[x]-dep[f];
for(int i=;i<=;i++)
if(t&(<<i)){
if(d1[x][i]>mx1){
mx2=mx1;
mx1=d1[x][i];}
mx2=max(mx2,d2[x][i]);
x=fa[x][i];
}
if(mx1!=v)mn=min(mn,v-mx1);
else mn=min(mn,v-mx2);}
void solve(int t,int v){
int x=a[t].x,y=a[t].y,f=lca(x,y);
cal(x,f,v);cal(y,f,v);}
int main(){
scanf("%d%d",&n,&m);
rep(i,,n) f[i]=i;
rep(i,,m) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);
sort(a+,a+m+,cmp);
rep(i,,m){
int xx=find(a[i].x),yy=find(a[i].y);
if(xx!=yy){
f[xx]=yy;
ans+=a[i].v;
a[i].sel=;
insert(a[i].x,a[i].y,a[i].v);
tot++;if(tot==n-)break;}
}dfs(,);
rep(i,,m) if(!a[i].sel)solve(i,a[i].v);
printf("%lld",ans+mn);
return ;
}
luogu 4180 严格次小生成树的更多相关文章
- 【luogu P4180 严格次小生成树[BJWC2010]】 模板
题目链接:https://www.luogu.org/problemnew/show/P4180 这个题卡树剖.记得开O2. 这个题inf要到1e18. 定理:次小生成树和最小生成树差距只有在一条边上 ...
- 洛谷.4180.[模板]次小生成树Tree(Kruskal LCA 倍增)
题目链接 构建完MST后,枚举非树边(u,v,w),在树上u->v的路径中找一条权值最大的边(权为maxn),替换掉它 这样在 w=maxn 时显然不能满足严格次小.但是这个w可以替换掉树上严格 ...
- BZOJ1977或洛谷4180 [BJWC2010]次小生成树
一道LCA+生成树 BZOJ原题链接 洛谷原题链接 细节挺多,我调了半天..累炸.. 回到正题,我们先求出随便一棵最小生成树(设边权和为\(s\)),然后扫描剩下所有边,设扫到的边的两端点为\(x,y ...
- [Luogu] 次小生成树
https://www.luogu.org/problemnew/show/P4180#sub 严格次小生成树,即不等于最小生成树中的边权之和最小的生成树 首先求出最小生成树,然后枚举所有不在最小生成 ...
- [Luogu P4180][BJWC 2010]严格次小生成树
严格次小生成树,关键是“严格”,如果是不严格的其实只需要枚举每条不在最小生成树的边,如果得到边权和大于等于最小生成树的结束就行.原理就是因为Kruskal非常贪心,只要随便改一条边就能得到一个非严格的 ...
- 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】
P4180 [模板]严格次小生成树[BJWC2010] 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说, ...
- Luogu P4180 【模板】严格次小生成树[BJWC2010]
P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得 ...
- 洛谷 P 4180 次小生成树
题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...
- 严格次小生成树(Bzoj1977:[Beijing2010组队]次小生成树)
非严格次小生成树 很简单,先做最小生成树 然后枚举没加入的边加入,替换掉这个环内最大的边 最后取\(min\) 严格次小生成树 还是一样的 可以考虑维护一个严格次大值 最大值和枚举的边相同就替换次大值 ...
随机推荐
- Python3 与 C# 并发编程之~ 线程篇
2.线程篇¶ 在线预览:https://github.lesschina.com/python/base/concurrency/3.并发编程-线程篇.html 示例代码:https://gith ...
- pycharm安装TensorFlow
一.首先说下我在安装TensorFlow的过程中遇到的坑: 1.python的版本是3.5的版本,因为TensorFlow好像只支持到3.5现在.然后python需要安装64位的安装包,如果安装的是3 ...
- spring代码异常捕获到logback logging.config=logback-spring.xml文件中不能输出异常e.printStackTrace
在spring中使用logging.config=logback-spring.xml将日志转存到了文件中.但是代码中的捕获的异常无法用 e.printStackTrace 打印到文件中.使用如下方法 ...
- 【CH0103】最短哈密顿路径
题目大意:给定一个 N 个点的无向图,点有点权,求从 0 号点走到 N-1 号点的最短哈密顿路径是多少. 题解:由于哈密顿路径的定义是每个顶点必须经过且仅能经过一次,因此,可用当前是否经过了这些点和当 ...
- Pandas库中的DataFrame
1 简介 DataFrame是Python中Pandas库中的一种数据结构,它类似excel,是一种二维表. 或许说它可能有点像matlab的矩阵,但是matlab的矩阵只能放数值型值(当然matla ...
- 第四节,Neural Networks and Deep Learning 一书小节(上)
最近花了半个多月把Mchiael Nielsen所写的Neural Networks and Deep Learning这本书看了一遍,受益匪浅. 该书英文原版地址地址:http://neuralne ...
- Hibernate 基础解析(Configuration,SessionFactory,Session,Transaction,Query,Criteria)
1 框架体系结构 对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实 现面向对象编程语言里 ...
- 安装原版Win8.1并激活
别问我为啥是win8.1,因为我不喜欢win10. 别问我为啥装系统,因为我新买了个硬盘. 别问我为啥写个教程,因为经历了很多坑. 第一步,用U启动做个U盘启动 http://www.uqdown.c ...
- UI 滑动面板的移动控制
通过拖拽的方式移动面板,在单个界面看到多个视图面板 需要导入UnityEngine.EventSystems; 事件命名空间 进而继承两个重要的接口IBeginDragHandler,IDrag ...
- Android app:transformNativeLibsWithStripDebugSymbolForDebug错误分析
升级NDK解决问题: 先清除 Android/Sdk/ndk-bundle/ 下的内容从 https://developer.android.google.cn/ndk/downloads/older ...