正题

题目链接: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. 个人笔记-----Vue中多个router-view应用

    单个 <router-view/> 和多个 <router-view/> 的区别,单个 <router-view/> 只是一个区域的变化,不需要设置name属性,在 ...

  2. UWP App Data存储和获取

    这篇博客介绍如何在UWP开发时,如何存储App Data和获取. App Data是指用户的一些设定,偏好等.例如,App的主题,是否接收推送,离线接收消息等.需要区分下App Data和User D ...

  3. echatrts 各参数快速了解(+实例)

    实例:https://www.jianshu.com/p/8cac22daca98 参数详解:https://echarts.baidu.com/option.html#title.textStyle ...

  4. FastReport.net 绿色破解版winform中使用

    FastReport 是非常有名的报表库,曾经在delphi中经常看到 现在FastReport.net 是.net平台下的实现.它的价格对于个人开发者来说确实非常非常贵 出于学习的目的(0<& ...

  5. 迭代器 与 foreach 的区别

    迭代器的常见运用--Eg:有一组数据 需要对每个符合条件的数据 进行记录 static void Main() { int[] s = new int[] { 1, 2, 8 }; foreach ( ...

  6. 超详细教程2021新版oracle官网下载Windows JAVA-jdk11并安装配置(其他版本流程相同)

    异想之旅:本人博客完全手敲,绝对非搬运,全网不可能有重复:本人无团队,仅为技术爱好者进行分享,所有内容不牵扯广告.本人所有文章发布平台为CSDN.博客园.简书和开源中国,后期可能会有个人博客,除此之外 ...

  7. 高德渲染网关Go语言重构实践

    ​1.导读 高德启动Go业务建设已经有段时间了,主要包含Go应用落地,Go中间件建设,云原生三个部分.经过持续的发力,在这些方面取得了不错的进展.高德Go业务落地过程是如何实现的,遇到过哪些问题,如何 ...

  8. for循环练习之打印三角形

    public class TestDemo01 { /** * 打印三角形 * 1.打印空格 * 2.打印三角形 */ public static void main(String[] args) { ...

  9. 分布式ID生成器及redis,etcd分布式锁

    分布式id生成器 有时我们需要能够生成类似MySQL自增ID这样不断增大,同时又不会重复的id.以支持业务中的高并发场景.比较典型的,电商促销时,短时间内会有大量的订单涌入到系统,比如每秒10w+.明 ...

  10. noip模拟35

    A. 玩游戏 考场做法用双指针向两侧更新,当左段点左移一位时,如果右端点不满足条件,则跳回肯定满足的位置.复杂度玄学 题解做法是类似最长子段和,如果有一个区间和为负,则维护的指针跳过去即可 B. 排列 ...