1977: [BeiJing2010组队]次小生成树 Tree

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 5168  Solved: 1668
[Submit][Status][Discuss]

Description

小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值) 这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

Input

第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。

Output

包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

Sample Input

5 6

1 2 1

1 3 2

2 4 3

3 5 4

3 4 3

4 5 6

Sample Output

11

HINT

数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。

Source

[Submit][Status][Discuss]

HOME
Back


题解

先求出最小生成树,要严格次小

枚举每一条非树边找俩顶点树链上的最大边(如果最大边相同与非树边边权相同则找次大边)然后更新最小增量

最大边和次大边可以通过树上倍增求出

复杂度是最小生成树\(m\log m\),枚举边乱搞\(m\log n\),所以是\(m\log nm\)

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std; co int N=1e5+1,M=3e5+1,INF=0x3f3f3f3f;
int n,m,t,fa[N],d[N],f[N][18];
struct edge{
int x,y,z,k;
bool operator<(co edge&e)co {return z<e.z;}
}p[M];
int g[N][18][2];
ll sum,ans=1e18;
vector<pair<int,int> > e[N];
int get(int x) {return fa[x]==x?x:fa[x]=get(fa[x]);}
void kruskal(){
sort(p+1,p+m+1);
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=1,x,y;i<=m;++i){
x=get(p[i].x),y=get(p[i].y);
if(x==y) continue;
fa[x]=y,sum+=p[i].z,p[i].k=1;
}
}
void dfs(int x){
for(int i=0,y;i<e[x].size();++i){
if(d[y=e[x][i].first]) continue;
d[y]=d[x]+1;
f[y][0]=x;
g[y][0][0]=e[x][i].second;
g[y][0][1]=-INF;
for(int j=1;j<=t;++j){
f[y][j]=f[f[y][j-1]][j-1];
g[y][j][0]=max(g[y][j-1][0],g[f[y][j-1]][j-1][0]);
if(g[y][j-1][0]==g[f[y][j-1]][j-1][0])
g[y][j][1]=max(g[y][j-1][1],g[f[y][j-1]][j-1][1]);
else if(g[y][j-1][0]<g[f[y][j-1]][j-1][0])
g[y][j][1]=max(g[y][j-1][0],g[f[y][j-1]][j-1][1]);
else g[y][j][1]=max(g[y][j-1][1],g[f[y][j-1]][j-1][0]);
}
dfs(y);
}
}
void lca(int x,int y,int&val1,int&val2){
if(d[x]>d[y]) swap(x,y);
for(int i=t;i>=0;--i)if(d[f[y][i]]>=d[x]){
if(val1>g[y][i][0]) val2=max(val2,g[y][i][0]);
else{
val1=g[y][i][0];
val2=max(val2,g[y][i][1]);
}
y=f[y][i];
}
if(x==y) return;
for(int i=t;i>=0;--i)if(f[x][i]!=f[y][i]){
val1=max(val1,max(g[x][i][0],g[y][i][0]));
val2=max(val2,g[x][i][0]!=val1?g[x][i][0]:g[x][i][1]);
val2=max(val2,g[y][i][0]!=val1?g[y][i][0]:g[y][i][1]);
x=f[x][i],y=f[y][i];
}
val1=max(val1,max(g[x][0][0],g[y][0][0]));
val2=max(val2,g[x][0][0]!=val1?g[x][0][0]:g[x][0][1]);
val2=max(val2,g[y][0][0]!=val1?g[y][0][0]:g[y][0][1]);
}
int main(){
read(n),read(m);
for(int i=1;i<=m;++i) read(p[i].x),read(p[i].y),read(p[i].z);
kruskal();
for(int i=1;i<=m;++i)if(p[i].k)
e[p[i].x].push_back(make_pair(p[i].y,p[i].z)),e[p[i].y].push_back(make_pair(p[i].x,p[i].z));
t=log(n)/log(2)+1;
d[1]=1;
for(int i=0;i<=t;++i) g[1][i][0]=g[1][i][1]=-INF;
dfs(1);
for(int i=1;i<=m;++i)if(!p[i].k){
int val1=-INF,val2=-INF;
lca(p[i].x,p[i].y,val1,val2);
if(p[i].z>val1) ans=min(ans,sum-val1+p[i].z);
else ans=min(ans,sum-val2+p[i].z);
}
printf("%lld\n",ans);
return 0;
}

[BeiJing2010组队]次小生成树 Tree的更多相关文章

  1. BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )

    做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...

  2. 1977: [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...

  3. 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增

    [BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...

  4. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  5. 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree

    Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...

  6. (luogu4180) [Beijing2010组队]次小生成树Tree

    严格次小生成树 首先看看如果不严格我们怎么办. 非严格次小生成树怎么做 由此,我们发现一个结论,求非严格次小生成树,只需要先用kruskal算法求得最小生成树,然后暴力枚举非树边,替换路径最大边即可. ...

  7. BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树

    描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...

  8. 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree

    Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...

  9. 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并

    题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...

随机推荐

  1. LVS的基础使用

    LVS的基础使用 LVS的介绍 A:什么是LVS B:cluster(集群的概念) C:LVS的介绍 LVS的使用 A:ipvsadm命令的使用 ♣一:LVS的介绍 A:什么是lvs LVS的英文全称 ...

  2. Apache软件基金会核心项目Tomcat的那些事

    Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选.今天就来为大家介绍一下关于T ...

  3. PostgreSQL的参数优化

    硬件和软件信息 CPU: Intel(R) Xeon(R) CPU E5-2683 v3 @ 2.00GHz 2 sockets / 28 cores / 56 threads内存: 256GB of ...

  4. SpringCloud——eureka集群

    目的: 第一种普通方式 第二种方式骚操作 Eureka自我保护机制 Eureka集群搭建 说的通俗易懂一点就是,同一个项目部署在多个服务器上. 当注册中心扛不住高并发的时候,这时候 要用集群来扛: 今 ...

  5. Elasticsearch-6.7.0系列(七)SpringCloud连接ES集群,使用ES用户名密码

    pom.xml代码: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://ww ...

  6. Microsoft.AspNet.Identity 自定义使用现有的表—登录实现,aspnet.identity

    Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现.Microsoft.AspNet.Identity.EntityFrame ...

  7. 玩转Spring全家桶笔记 03 Spring的JDBC操作以及SQL批处理的实现

    1 spring-jdbc core JdbcTemplate 等相关核心接口和类(核心) datesource 数据源相关的辅助类(内嵌数据源的初始化) object 将基本的JDBC操作封装成对象 ...

  8. 关于移动端图片浏览,previewimage的使用

    我相信在移动端项目中,大家都会遇到图片浏览的问题,像qq,微信,微博,淘宝,当你点击图片时,图片会放大全屏显示,双击图片时图片继续放大查看,双指左右滑动也可以放大,当你再次点击时图片,图片恢复原始大小 ...

  9. 开发QQ互联ios版Ane扩张 辛酸史

    来源:http://www.myexception.cn/operating-system/1451490.html 开发QQ互联ios版Ane扩展 辛酸史 开发QQ互联ios版Ane扩展辛酸史: 1 ...

  10. python3实现unix域协议(tcp、udp)通讯

    socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIXDomain Socket.虽然网络socket也可用于同一台主机的进程间通讯(通过loopb ...