次小生成树,顾名思义和次短路的思路似乎很类似呀,

于是就先写了个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 严格次小生成树的更多相关文章

  1. 【luogu P4180 严格次小生成树[BJWC2010]】 模板

    题目链接:https://www.luogu.org/problemnew/show/P4180 这个题卡树剖.记得开O2. 这个题inf要到1e18. 定理:次小生成树和最小生成树差距只有在一条边上 ...

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

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

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

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

  4. [Luogu] 次小生成树

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

  5. [Luogu P4180][BJWC 2010]严格次小生成树

    严格次小生成树,关键是“严格”,如果是不严格的其实只需要枚举每条不在最小生成树的边,如果得到边权和大于等于最小生成树的结束就行.原理就是因为Kruskal非常贪心,只要随便改一条边就能得到一个非严格的 ...

  6. 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】

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

  7. Luogu P4180 【模板】严格次小生成树[BJWC2010]

    P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得 ...

  8. 洛谷 P 4180 次小生成树

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

  9. 严格次小生成树(Bzoj1977:[Beijing2010组队]次小生成树)

    非严格次小生成树 很简单,先做最小生成树 然后枚举没加入的边加入,替换掉这个环内最大的边 最后取\(min\) 严格次小生成树 还是一样的 可以考虑维护一个严格次大值 最大值和枚举的边相同就替换次大值 ...

随机推荐

  1. CF1139D Steps to One(DP,莫比乌斯反演,质因数分解)

    stm这是div2的D题……我要对不住我这个紫名了…… 题目链接:CF原网  洛谷 题目大意:有个一开始为空的序列.每次操作会往序列最后加一个 $1$ 到 $m$ 的随机整数.当整个序列的 $\gcd ...

  2. nio再学习之通道channel

    通道(Channel):用于在数据传输过程中,进行输入输出的通道,其与(流)Stream不一样,流是单向的,在BIO中我们分为输入流,输出流,但是在通道中其又具有读的功能也具有写的功能或者两者同时进行 ...

  3. angular与vue的应用对比

    因为各种笔试面试,最近都没时间做一些值得分享的东西,正好复习一下vue技术栈,与angular做一下对比. angular1就跟vue比略low了. 1.数据绑定 ng1 ng-bind,{{ sco ...

  4. Spring 依赖注入优化

    Spring 依赖注入优化 原创: carl.zhao SpringForAll社区 今天 Spring 最大的好处就是依赖注入,关于什么是依赖注入,在Stack Overflow上面有一个问题,如何 ...

  5. jackson json转对象 对象转json

    一,Jackson使用示例 第1步:创建ObjectMapper对象. 创建ObjectMapper对象.它是一个可重复使用的对象. ObjectMapper mapper = new ObjectM ...

  6. 纪中2018暑假培训day1提高b组改题记录

    收到意见,认为每天的程序和随笔放在一起写的博客太长了,于是分开整理 day1 模拟赛,看了看提高a组t1的样例就不太想写,于是转而写b组 t1: Description 给定一个n个点m条边的有向图, ...

  7. Java IO流篇

    什么是IO流 思考问题 如何读写文件? 解决--通过流读写文件 流是指一连串流动的字符,以先进先出传输信息的通道. Java操控硬盘上的文件,通过IO流来实现 Java流的分类 按流向区分 ---输出 ...

  8. tensorflow不同版本安装与升级/降级

    https://blog.csdn.net/junmuzi/article/details/78357371 首先,可以安装一个anaconda. 然后使用python的pip可以安装特定版本的ten ...

  9. java 分隔函数split("",-1)的用途

    转: java 分隔函数split("",-1)的用途 2017年12月14日 11:37:58 jaryle 阅读数:8517   1.如果字符串最后一位有值,则没有区别, 2. ...

  10. C++的静态成员变量使用方法

    main.cpp:(.text._ZN6Object4useSEv[_ZN6Object4useSEv]+0x1a):对‘Object::i’未定义的引用 常用Java不懂C++的静态方法使用方式.尝 ...