次小生成树(lca)
题目描述
原题来自:BeiJing 2010 组队赛
给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树。
设最小生成树的边权之和为 sum,严格次小生成树就是指边权之和大于 sum 的生成树中最小的一个。
输入格式
第一行包含两个整数 N 和 M,表示无向图的点数与边数;
接下来 M 行,每行三个数 x,y,z表示点 x和点 y 之间有一条边,边的权值为 z。
输出格式
包含一行,仅一个数,表示严格次小生成树的边权和。
数据保证必定存在严格次小生成树。
样例
样例输入
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
样例输出
11
- #include<bits/stdc++.h>
- const int MAXN=,MAXM=;
- using namespace std;
- int n,m,N;
- struct E{
- int u,v,f;
- long long val;
- }a[MAXM*];
- bool mw(E a,E b)
- {
- return a.val<b.val;
- }
- struct Edge{
- int to,next;
- long long val;
- }edge[MAXM*];
- int head[MAXN],num=;
- int fa[MAXN],find();
- long long ans,mn=;
- int f[MAXN][],dep[MAXN];
- long long d1[MAXN][],d2[MAXN][];
- inline void add(int u,int v,long long val)
- {
- edge[++num].next=head[u];
- edge[num].to=v;
- edge[num].val=val;
- head[u]=num;
- return;
- }
- inline int find(int a)
- {
- return a==fa[a]?a:fa[a]=find(fa[a]);
- }
- inline void grow()
- {
- int u,v,val,cnt=;
- sort(a+,a+m+,mw);
- int r1,r2;
- for(register int i=;i<=n;++i)fa[i]=i;
- for(register int i=;i<=m;++i)
- {
- u=a[i].u,v=a[i].v,val=a[i].val;
- r1=find(u);
- r2=find(v);
- if(r1!=r2)
- {
- cnt++;
- a[i].f=;
- add(u,v,val);
- add(v,u,val);
- fa[r1]=r2;
- ans+=val;
- if(cnt==n-) break;
- }
- }
- return;
- }
- inline void dfs(int u)
- {
- for(register int i=;i<=N;i++)
- {
- f[u][i]=f[f[u][i-]][i-];
- d1[u][i]=max(d1[u][i-],d1[f[u][i-]][i-]);
- if(d1[u][i-]==d1[f[u][i-]][i-])
- d2[u][i]=max(d2[u][i-],d2[f[u][i-]][i-]);
- else
- {
- d2[u][i]=min(d1[u][i-],d1[f[u][i-]][i-]);
- d2[u][i]=max(d2[u][i-],d2[u][i]);
- d2[u][i]=max(d2[u][i],d2[f[u][i-]][i-]);
- }
- }
- for(register int i=head[u];i;i=edge[i].next)
- {
- int v=edge[i].to;
- if(v==f[u][])continue;
- f[v][]=u;
- d1[v][]=edge[i].val;
- dep[v]=dep[u]+;
- dfs(v);
- }
- return;
- }
- inline int lca(int a,int b)
- {
- if(dep[a]>dep[b]) swap(a,b);
- for(register int i=N;i>=;i--)
- {
- if(dep[a]<dep[b]&&dep[f[b][i]]>=dep[a]) b=f[b][i];
- }
- if(a==b)return a;
- for(register int i=N;i>=;i--)
- {
- if(f[a][i]!=f[b][i]){a=f[a][i],b=f[b][i];}
- }
- return f[a][];
- }
- inline void Try(int u,int father,long long val)
- {
- int t;
- t=dep[u]-dep[father];
- long long mx1=-,mx2=;
- for(int i=;i<=N;i++)
- {
- if(t&(<<i))//注意这一步!!
- {
- if(mx1<=d1[u][i])
- {
- mx2=mx1;
- mx1=d1[u][i];
- mx2=max(mx2,d2[u][i]);
- }
- else
- {
- mx2=max(mx2,d1[u][i]);
- }
- u=f[u][i];//写的好神奇
- }
- }
- if(mx1!=val)
- {
- if(mn>val-mx1)
- {
- mn=val-mx1;
- }
- }
- else
- {
- if(mn>val-mx2)
- {
- mn=val-mx2;
- }
- }
- return;
- }
- inline void choose()
- {
- int f,u,v,val;
- for(register int i=;i<=m;++i)
- {
- if(a[i].f==)
- continue;
- u=a[i].u;
- v=a[i].v;
- val=a[i].val;
- f=lca(u,v);
- Try(u,f,val),Try(v,f,val);
- }
- return;
- }
- int main()
- {
- scanf("%d%d",&n,&m);
- for(register int i=;i<=m;++i)
- {
- scanf("%d%d%lld",&a[i].u,&a[i].v,&a[i].val);
- }
- grow();
- N=floor(log(n+0.0)/log(2.0));
- dfs();
- choose();
- printf("%lld",ans+mn);
- return ;
- }
次小生成树(lca)的更多相关文章
- 次小生成树(LCA倍增)
算法: 求出MST之后枚举每条在MST之外的边 连上之后会出现环 找到环中除加上的边之外权值最大的边 删除该边之后得到一颗新树 做法: 利用LCA倍增地维护最小生成树上两点之间的最大边权 每次枚举在M ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- 洛谷P4180 [BJWC2010]次小生成树(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
- [bzoj1977][BeiJing2010组队]次小生成树 Tree——树上倍增+lca
Brief Description 求一个无向图的严格次小生成树. Algorithm Design 考察最小生成树的生成过程.对于一个非树边而言,如果我们使用这一条非树边去替换原MST的路径上的最大 ...
- 「LuoguP4180」 【模板】严格次小生成树[BJWC2010](倍增 LCA Kruscal
题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...
- 严格次小生成树(lca + 倍增)
题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...
- 树的问题小结(最小生成树、次小生成树、最小树形图、LCA、最小支配集、最小点覆盖、最大独立集)
树的定义:连通无回路的无向图是一棵树. 有关树的问题: 1.最小生成树. 2.次小生成树. 3.有向图的最小树形图. 4.LCA(树上两点的最近公共祖先). 5.树的最小支配集.最小点覆盖.最大独立集 ...
- [BJWC2010]严格次小生成树(LCA,最小生成树)
[BJWC2010]严格次小生成树 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图 ...
随机推荐
- 最常见的Java面试题及答案汇总(五)
Java Web 64. jsp 和 servlet 有什么区别? jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器 ...
- Activiti Service介绍
原文地址:https://www.cnblogs.com/lyh421/p/6419518.html 第一章 认识Activiti 内容概览:讲解activiti的特点.接口概览.架构等基本信息. 1 ...
- netty的reactor模式
reactor中包含5个核心结构,那么从操作系统低层次的调度来看5部分是这样的. (1)Handle(句柄资源描述符)本质是对客户端连接上来以后发生事件的处理机制,比如连接成功,读取数据,发送数据等状 ...
- Delphi TButton.OnClick 匿名函数用法
type TNotifyEventRef = reference to procedure(Sender: TObject); function AnonymousEvent(const Proc: ...
- Java 中的 equals,==与 hashCode 的区别与联系
一. 关系操作符 ==:若操作数的类型是基本数据类型,则该关系操作符判断的是左右两边操作数的值是否相等若操作数的类型是引用数据类型,则该关系操作符判断的是左右两边操作数的内存地址是否相同.也就是说,若 ...
- flink checkpoint状态储存三种方式选择
Flink 提供了三种可用的状态后端:MemoryStateBackend,FsStateBackend,和RocksDBStateBackend. MemoryStateBackend Memory ...
- SQL SERVER 查询所有表大小
DECLARE @T TABLE ( [name] VARCHAR(max), [rows] INT, reserved VARCHAR(max), data_size VARCHAR(max), i ...
- sparksql读取hive数据报错:java.lang.RuntimeException: serious problem
问题: Caused by: java.util.concurrent.ExecutionException: java.lang.IndexOutOfBoundsException: Index: ...
- 2019-07-23 php魔术方法
本文对一些php中的魔术方法进行总结,魔术方法顾名思义就是具备神奇功能的方法(function).魔术方法通常在某些特定情况下自动触发,不能用实例化变量名->方法名()来主动触发.不同的魔术方法 ...
- Java GC的工作原理详解
JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代下载地址 和旧生代采用不同的垃圾回收机制. 首先来看一下JVM内存结 ...