正题

题目链接:https://www.luogu.com.cn/problem/AT3611


题目大意

给出\(n\)个点的一棵树。

现在有一张完全图,两个点之间的边权为\(w_x+w_y+dis(x,y)\)(\(dis\)表示树上距离)

求这张完全图的最小生成树。

\(2\leq n\leq 2\times 10^5,1\leq w_i,c_i\leq 10^9\)


解题思路

考虑可能作为最小生成树的边。

一个结论就是对于一个子图。不在最小生成森林上的边一定不在原图的最小生成树上。

这样可以考虑分治,点分治之后对于根节点\(x\),其他的节点定义\(f_x=dep_x+w_x\),那么两个点之间边权就是\(f_x+f_y\)了(\(x,y\)属于不同子树),对于同一子树的我们也加进去,因为这是不优的边所以不会影响答案。

此时图中的最小生成森林是其他所有点连接\(f\)值最小的点。

这样我们可以处理出\(n\log n\)条可能的边,在这些边上再跑一次最小生成树就好了。

时间复杂度\(O(n\log^2 n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,inf=1e18;
struct node{
ll to,next,w;
}a[N<<1];
struct edge{
ll x,y,w;
}e[N<<5];
ll n,tot,mins,root,ans,num,ent;
ll ls[N],f[N],siz[N],w[N],fa[N];
bool v[N];
void addl(ll x,ll y,ll w){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;a[tot].w=w;
return;
}
void groot(ll x,ll fa){
siz[x]=1;f[x]=0;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa||v[y])continue;
groot(y,x);siz[x]+=siz[y];
f[x]=max(f[x],siz[y]);
}
f[x]=max(f[x],num-siz[x]);
if(f[x]<f[root])root=x;
return;
}
void calc(ll x,ll fa,ll dep){
f[x]=w[x]+dep;
if(f[x]<f[mins])mins=x;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa||v[y])continue;
calc(y,x,dep+a[i].w);
}
return;
}
void adde(ll x,ll fa){
e[++ent]=(edge){x,mins,f[x]+f[mins]};
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa||v[y])continue;
adde(y,x);
}
}
void solve(ll x){
v[x]=1;f[x]=w[mins=x];
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(v[y])continue;
calc(y,x,a[i].w);
}
e[++ent]=(edge){x,mins,f[x]+f[mins]};
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(v[y])continue;
adde(y,x);
}
ll sum=num;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(v[y])continue;
num=(siz[y]>siz[x])?(sum-siz[x]):siz[y];
root=0;groot(y,x);solve(root);
}
return;
}
bool cmp(edge x,edge y)
{return x.w<y.w;}
ll find(ll x)
{return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
signed main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
scanf("%lld",&w[i]),fa[i]=i;
for(ll i=1;i<n;i++){
ll x,y,w;
scanf("%lld%lld%lld",&x,&y,&w);
addl(x,y,w);addl(y,x,w);
}
num=n;f[0]=inf;
groot(1,1);solve(root);
sort(e+1,e+1+ent,cmp);
for(ll i=1;i<=ent;i++){
ll x=e[i].x,y=e[i].y;
x=find(x);y=find(y);
if(x!=y)ans+=e[i].w,fa[y]=x;
}
printf("%lld\n",ans);
return 0;
}

AT3611-Tree MST【点分治,最小生成树】的更多相关文章

  1. AT3611 Tree MST 点分治+最小生成树

    正解:点分治+最小生成树 解题报告: 传送门! 然后这题麻油翻译,,,所以这边的建议是先说下题意呢亲 所以题意大概就是说,给一棵n个节点的树,树上每个点都有个权值,然后构造一个完全图,(u,v)之间连 ...

  2. AT3611 Tree MST

    题面 题解 考虑最小化\(dis(x, y)\) 这里需要对一种奇怪的最小生成树算法:Boruvka算法有深刻的理解. 考虑该算法的执行过程,我们可以考虑进行点分治,每次找到离分治重心最近的点,然后将 ...

  3. 【AtCoder3611】Tree MST(点分治,最小生成树)

    [AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...

  4. hdu 4670 Cube number on a tree(点分治)

    Cube number on a tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/ ...

  5. 【POJ1741】Tree(点分治)

    [POJ1741]Tree(点分治) 题面 Vjudge 题目大意: 求树中距离小于\(K\)的点对的数量 题解 完全不觉得点分治了.. 简直\(GG\),更别说动态点分治了... 于是来复习一下. ...

  6. 最小生成树 (Minimum Spanning Tree,MST) --- Prim算法

    本文链接:http://www.cnblogs.com/Ash-ly/p/5409904.html 普瑞姆(Prim)算法: 假设N = (V, {E})是连通网,TE是N上最小生成树边的集合,U是是 ...

  7. 最小生成树 (Minimum Spanning Tree,MST) --- Kruskal算法

    本文链接:http://www.cnblogs.com/Ash-ly/p/5409265.html 引导问题: 假设要在N个城市之间建立通信联络网,则连通N个城市只需要N - 1条线路.这时,自然会考 ...

  8. 【AT3611】Tree MST

    题目 这个题的输入首先就是一棵树,我们考虑一下点分 我们对于每一个分治重心考虑一下跨过这个分治重心的连边情况 就是把当前分治区域内所有的点向距离分治重心最近的点连边 考虑一下这个算法的正确性,如果我们 ...

  9. poj 1679 The Unique MST(唯一的最小生成树)

    http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submis ...

随机推荐

  1. malloc 和new , free 和delete的区别

    #include <iostream>using namespace std;class user{ public: int age; int number; void test() { ...

  2. mybatis学习日志一

    Mybatis 介绍 MyBatis 是支持 普通 SQL 查询 , 存储过程 和 高级映射 的优秀持久层框架.MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以 及对结果集的检索封装 ...

  3. SpringBoot中自定义错误页面

    错误页面定制(在有模板引擎的情况下): 有模板的支持下: 在templates文件夹下 建立 error文件夹 在error文件夹下 404.html 500.html 4xx.html (名字就叫4 ...

  4. Alibaba cloud 3 安装docker

    最近因为公司买阿里服务器装的 Alibaba cloud Linux 系统,在部署环境的时候也是遇到各种坑,网上教程大多都是其他系统的,今天就来分享一下自己安装Docker的步骤,同时也是给自己记录一 ...

  5. Jmeter的默认字体和窗口的设置方法(一次改动,永久生效!!!)

    因为每次打开jmeter看到的界面不如意,而且会影响工作发挥和效率,为了给大家带来良好的工作体验,为此给出最完美的设置方法,如下: 第一步: 找到jmeter所在目录--->bin---> ...

  6. 如何将excel中纵向的转换成横向保证格式不变,

    先选定,复制,然后用--编辑---选择性粘贴--转置--确定.试试能不能实现 ,能把文件发过来看一下​

  7. 遇到Web页面禁用鼠标右键操作时,该如何解禁?

    在使用Selenium做Web UI自动化测试过程中,经常需要鼠标右击Web页面检查DOM节点,用于获取Web元素的定位信息.一般情况下,绝大多数页面都是能够响应鼠标右击操作的.但出于某些目的,有些W ...

  8. Django——ORM打印SQL

    如果想打印ORM转换过程中的SQL,需要在settings.py中进行如下配置: LOGGING = { 'version': 1, 'disable_existing_loggers': False ...

  9. uni-app中websocket的使用 断开重连、心跳机制

    前言 最近关于H5和APP的开发中使用到了webSocket,由于web/app有时候会出现网络不稳定或者服务端主动断开,这时候导致消息推送不了的情况,需要客户端进行重连.查阅资料后发现了一个心跳机制 ...

  10. Linux常用命令 - rm命令详解

    21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 删除/ ...