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

于是就先写了个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. [SCOI2015]国旗计划[Wf2014]Surveillance

    [SCOI2015]国旗计划 A国正在开展一项伟大的计划——国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这 项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名 ...

  2. Mysql 系统表

    Information_schema: 1. tables 提供表信息: 表所属数据库,表名,表类型,行数,最大自增数等等.

  3. 20165223 Linux安装及命令入门

    预备作业3:Linux安装及命令入门 一.VirtualBox和Ubuntu的安装 通过学习实践基于VirtualBox虚拟机安装Ubuntu图文教程,我开始学习虚拟机的安装,根据教程一步步试着安装. ...

  4. Ubuntu18.04搜狗输入法最新版本2.2.0.0108经常乱码的解决方案

    图示 解决 旧版 可以安装旧版(我只在新版sogoupinyin_2.2.0.0108_amd64才遇到这个问题) 旧版安装指南:http://www.cnblogs.com/dunitian/p/6 ...

  5. jenkins自动打包部署项目

    首先去jenkins的官网下载安装包 https://jenkins.io/   个人下载是长期稳定的那个版本,下载后,得到一个.msi的安装包: 点击进行安装,然后一直点击下一步. jenkins会 ...

  6. 使用Spring Cloud连接不同服务

    http://www.infoq.com/cn/articles/spring-cloud-service-wiring 主要结论 Spring Cloud为微服务系统中相互依赖的服务提供了丰富的连接 ...

  7. JQuery选择器,事件,DOM操作,动画

    JQuery是一个JavaScript代码库,或者是JavaScript框架: 1.选择器:(和CSS选择器一致) 基本选择器:ID选择器$('#div1');Class选择器('.div1');标签 ...

  8. 终于解决了用JAVA写窗口程序在不同的windows界面下的显示保持一致。

    好像是两三年前的时候发现这个问题. 由于在windows经典界面与windows xp界面下,窗口的标题栏的高度是不一样的. 所以我们在用Java写GUI程序的时候,会遇到一个问题. 当我把一个JFr ...

  9. Spring MVC 架构的java web工程如何添加登录过滤器

    发布到外网的web工程必须添加登录过滤器来阻挡一些非法的请求,即只有登录的用户才能对web工程进行请求,否则无论请求什么资源都需要调整到登录页面进行登录操作.这时就需要用到过滤器,其实非常简单,只需要 ...

  10. unsigned 变量名:n

    在结构体内定义位,节省空间 /* * size是字节数 * addr是打印的起始地址 */ static void printb(void * addr,size_t size){ ;i<siz ...