【AT3611】Tree MST
这个题的输入首先就是一棵树,我们考虑一下点分
我们对于每一个分治重心考虑一下跨过这个分治重心的连边情况
就是把当前分治区域内所有的点向距离分治重心最近的点连边
考虑一下这个算法的正确性,如果我们已经对一个联通块内部形成了一个\(mst\),我们需要把这个联通块和另外一个联通块合并
如果这个新的联通块出现会使得原来联通块的\(mst\)改变,那么新出现的边也只会是原来联通块的点和新联通块到这个点距离最近的点之间的边,而这些最近的点又都是一个,所以我们就可以大大简化连边数量了
所以这个点分的过程就相当于合并\(mst\)的过程
我们点分之后发现我们连了大概\(nlogn\)条边,于是再跑一个kruskal就好了,复杂度\(O(nlog^2n)\)
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int maxn=2e5+5;
struct E{int v,nxt,w;}e[maxn<<1];
struct Edge{int a,b;LL c;}E[maxn*55];
int sum[maxn],vis[maxn],head[maxn],mx[maxn],a[maxn],fa[maxn],sz[maxn];
int n,num,m,dx,S,rt;LL dw,ans,pre[maxn];
inline void add(int x,int y,int z) {
e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=z;
}
void getroot(int x,int fa) {
sum[x]=1,mx[x]=0;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||e[i].v==fa) continue;
getroot(e[i].v,x);sum[x]+=sum[e[i].v];
mx[x]=max(mx[x],sum[e[i].v]);
}
mx[x]=max(mx[x],S-sum[x]);
if(mx[x]<mx[rt]) rt=x;
}
void getdis(int x,int fa) {
E[++m]=(Edge){dx,x,pre[x]+a[x]+dw};
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||e[i].v==fa) continue;
getdis(e[i].v,x);
}
}
void chk(int x,int fa) {
if(pre[x]+a[x]<dw) dw=pre[x]+a[x],dx=x;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||e[i].v==fa) continue;
pre[e[i].v]=pre[x]+e[i].w;chk(e[i].v,x);
}
}
void dfs(int x) {
dx=x,dw=a[x];vis[x]=1;pre[x]=0,chk(x,0),getdis(x,0);
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
S=sum[e[i].v],rt=0,getroot(e[i].v,0),dfs(rt);
}
}
inline int cmp(Edge A,Edge B) {return A.c<B.c;}
inline int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
inline int merge(int x,int y) {
int xx=find(x),yy=find(y);
if(xx==yy) return 0;
if(sz[xx]<sz[yy]) fa[xx]=yy,sz[yy]+=sz[xx];
else fa[yy]=xx,sz[xx]+=sz[yy];
return 1;
}
int main() {
n=read();
for(re int i=1;i<=n;i++) a[i]=read();
for(re int x,y,z,i=1;i<n;i++)
x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
mx[0]=n+1,S=n,rt=0,getroot(1,0),dfs(rt);
std::sort(E+1,E+m+1,cmp);
for(re int i=1;i<=n;i++) sz[i]=1,fa[i]=i;
for(re int i=1;i<=m;i++) if(merge(E[i].a,E[i].b)) ans+=E[i].c;
std::cout<<ans;
return 0;
}
【AT3611】Tree MST的更多相关文章
- 【AtCoder3611】Tree MST(点分治,最小生成树)
[AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...
- 【POJ3237】Tree 树链剖分+线段树
[POJ3237]Tree Description You are given a tree with N nodes. The tree's nodes are numbered 1 through ...
- 【BZOJ】【2631】Tree
LCT 又一道名字叫做Tree的题目…… 看到删边加边什么的……又是动态树问题……果断再次搬出LCT. 这题比起上道[3282]tree的难点在于需要像线段树维护区间那样,进行树上路径的权值修改&am ...
- 【Luogu1501】Tree(Link-Cut Tree)
[Luogu1501]Tree(Link-Cut Tree) 题面 洛谷 题解 \(LCT\)版子题 看到了顺手敲一下而已 注意一下,别乘爆了 #include<iostream> #in ...
- 【BZOJ3282】Tree (Link-Cut Tree)
[BZOJ3282]Tree (Link-Cut Tree) 题面 BZOJ权限题呀,良心luogu上有 题解 Link-Cut Tree班子提 最近因为NOIP考炸了 学科也炸了 时间显然没有 以后 ...
- 【AtCoder2134】ZigZag MST(最小生成树)
[AtCoder2134]ZigZag MST(最小生成树) 题面 洛谷 AtCoder 题解 这题就很鬼畜.. 既然每次连边,连出来的边的权值是递增的,所以拿个线段树xjb维护一下就可以做了.那么意 ...
- 【HDU5909】Tree Cutting(FWT)
[HDU5909]Tree Cutting(FWT) 题面 vjudge 题目大意: 给你一棵\(n\)个节点的树,每个节点都有一个小于\(m\)的权值 定义一棵子树的权值为所有节点的异或和,问权值为 ...
- 【BZOJ2654】Tree(凸优化,最小生成树)
[BZOJ2654]Tree(凸优化,最小生成树) 题面 BZOJ 洛谷 题解 这道题目是之前\(Apio\)的时候写的,忽然发现自己忘记发博客了... 这个万一就是一个凸优化, 给所有白边二分一个额 ...
- 【POJ1741】Tree(点分治)
[POJ1741]Tree(点分治) 题面 Vjudge 题目大意: 求树中距离小于\(K\)的点对的数量 题解 完全不觉得点分治了.. 简直\(GG\),更别说动态点分治了... 于是来复习一下. ...
随机推荐
- Java——面向对象的特征三:多态性
2.5面向对象的特征三:多态性 2.5.1 关于java语言中的向上转型和向下转型 ①向上转型(upcasting) : 子--->父(自动类型转换) ②向下转型(downcasting) : ...
- thinkphp 域名部署
ThinkPHP支持模块(甚至可以包含控制器)的完整域名.子域名和IP部署功能,让你的模块变得更加灵活,模块绑定到域名或者IP后,URL地址中的模块名称就可以省略了,所以还可以起到简化URL的作用. ...
- 帝国cms过滤采集内容
在过滤广告正则的[!--ad--]标识处,加上过滤正则即可 https://jingyan.baidu.com/article/c275f6bae3ea0de33d75671c.html
- 从[id setValue: forKey:]了解KVC
<Objective-C基础教程> P224页有详细介绍 下边是apple官网的简单介绍 和一个应用的例子. KVC就是Key-value coding,大意是允许通过一个Key来读写一个 ...
- 求树的最大独立集,最小点覆盖,最小支配集 贪心and树形dp
目录 求树的最大独立集,最小点覆盖,最小支配集 三个定义 贪心解法 树形DP解法 (有任何问题欢迎留言或私聊&&欢迎交流讨论哦 求树的最大独立集,最小点覆盖,最小支配集 三个定义 最大 ...
- python list基本操作一
a = [1,2,3,1,2,3] 一.删除元素 1.按索引删除: a.pop(1) # 删除第二个值 # in:[1,2,3,2] # out:[1,3,2] 返回值:被删除的元素,这个时候list ...
- 无法启动此程序,因为计算机中丢失api-ms-win-crt-runtime-l1-1-0.dll已解决
问题 : 无法启动此程序,因为计算机中丢失api-ms-win-crt-runtime-l1-1-0.dll 解决 1, 首先把C:\Windows\SysWOW64\的api-ms-win-crt- ...
- HDU 2874 /// tarjan离线求森林里两点的距离
题目大意: 在一个森林里 询问 u v 两点 若不能到达输出 "Not connected" 否则输出两点距离 https://blog.csdn.net/keyboarderqq ...
- Crane /// 向量旋转+线段树
题目大意: 给定n条首尾相接的线段的长度 第一条从0,0开始,所有线段垂直与x轴向上延伸 给定c次操作 每次操作给定 s,a 使得 由第s条线段的角度 逆时针旋转a后 达到第s+1条线段的角度 每次操 ...
- Oracle学习01-Oracle的基本查询和过滤排序