[CodeFestival 2017J]MST
MST
题解
首先我们知道,如果我们将原本的的边集分成两部分,对其分别求最小生成树(即使建不出完整的树也没关系),再将这两部分中是最小生成树的边集合在一起,求最小生成树,我们求出来的最小生成树一定是原边集的最小生成树。
这东西通过Kruskal的方法是很容易证明的,毕竟原边集最小生成树的边肯定都会选进边集子集的最小生成树。
原题目的两点间加边的代价为valu+valv+dist(u,v)val_{u}+val_{v}+dist(u,v)valu+valv+dist(u,v),所以应该很容易联想到通过点分治来求出哪些边可能成为最小生成树的边。
我们设当前子树的重心为uuu,我们可以将当前子树内的边集分成两部分:
两端点都在重心的每个子树内的边与两个端点中有一个在重心上或两个端点在不同的子树上。
显然,第一类的边在每棵子树上是独立的,我们可以下传到该子树内去求。
而对于第二类的边,我们考虑哪些边是可能被选取的。
我们定义disi=vali+dist(u,i)dis_{i}=val_{i}+dist(u,i)disi=vali+dist(u,i),很显然,对于两个不在同一棵上的两点,它们是一定会过我们的重心的,连接(x,y)(x,y)(x,y)的代价为disx+disydis_{x}+dis_{y}disx+disy。
显然,我们在连接这棵树的最小生成树时,这部分的边会加入的只有可能有每个点与disdisdis值最小的点之间连边。
所以我们可以去找出这棵树内disdisdis值最小的点,将它与该树内其它点直接的边加进去。
显然,这些点此时与其它点之间最短的边都是与该点的边,可以跟BruvkaBruvkaBruvka一样理解,我们此时加入的边一定是这条边,该点与其他点的边一定不会在这层加入。
很明显,根据点分治,我们加入的边总数是nlognnlog\,nnlogn级别的,我们此时可以通过Kruskal边集的最小生成树。
时间复杂度O(nlogn)O\left(n\log\,n\right)O(nlogn)。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int n1=50;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){putchar('\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,siz[MAXN],Rt,N,mx,head[MAXN],tot,disk[MAXN],cnt,fa[MAXN];
LL dis[MAXN],val[MAXN],dep[MAXN],ans;
bool vis[MAXN];
vector<int>vec;
struct ming{int u,v;LL w;}s[MAXN*30];
bool cmp(ming x,ming y){return x.w<y.w;}
struct edge{int to,nxt;LL paid;}e[MAXN<<1];
void addEdge(int u,int v,int w){e[++tot]=(edge){v,head[u],(LL)w};head[u]=tot;}
void findRoot(int u,int fa){siz[u]=1;int maxx=0;for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(v==fa||vis[v])continue;findRoot(v,u);siz[u]+=siz[v];maxx=max(maxx,siz[v]);}maxx=max(maxx,N-siz[u]);if(maxx<mx)mx=maxx,Rt=u;
}
void dosaka(int u,int fa){dis[u]=dep[u]+val[u];disk[u]=u;siz[u]=1;vec.pb(u);for(int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(v==fa||vis[v])continue;dep[v]=dep[u]+e[i].paid;dosaka(v,u);siz[u]+=siz[v];if(dis[v]<dis[u])dis[u]=dis[v],disk[u]=disk[v];}
}
void sakura(int u){N=siz[u];if(N==1)return ;Rt=0;mx=INF;vec.clear();findRoot(u,0);dep[Rt]=0;dosaka(Rt,0);u=Rt;int siz=vec.size();vis[u]=1;//printf("sakura %d:%lld %d\n",u,dis[u],disk[u]);for(int i=0;i<siz;i++)s[++cnt]=(ming){disk[u],vec[i],dep[vec[i]]+val[vec[i]]+dis[u]};for(int i=head[u];i;i=e[i].nxt)if(!vis[e[i].to])sakura(e[i].to);
}
void makeSet(int x){for(int i=1;i<=x;i++)fa[i]=i;}
int findSet(int x){return fa[x]==x?x:fa[x]=findSet(fa[x]);}
void unionSet(int a,int b){int u=findSet(a),v=findSet(b);if(u^v)fa[u]=v;}
signed main(){read(n);for(int i=1;i<=n;i++)read(val[i]);int tim=0;for(int i=1,u,v,w;i<n;i++)read(u),read(v),read(w),addEdge(u,v,w),addEdge(v,u,w);siz[1]=n;sakura(1);makeSet(n);sort(s+1,s+cnt+1,cmp);for(int i=1;i<=cnt;i++){int u=s[i].u,v=s[i].v;LL w=s[i].w;if(findSet(u)==findSet(v))continue;unionSet(u,v);ans+=w;tim++;if(tim==n-1)break;}printf("%lld\n",ans);return 0;
}
谢谢!!!
[CodeFestival 2017J]MST相关推荐
- php修改时区MST,4、修改Cacti绘图的时间精度
一.前言 前面几篇记录了怎么去安装Cacti,这篇呢主要记录下如何修改Cacti绘图的精度,注意是绘图的精度而不是轮询的精度.在开始写这篇笔记的时候首先得谢谢帮助我解决PHP问题的ikodota. C ...
- hdu1863 畅通工程---MST连通
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1863 题目大意: 中文题,求MST权值,如果不连通,输出? 解题思路: 这道题帮我找出了之前模板中的 ...
- POJ 1679 - The Unique MST(次小生成树)
题目链接 https://vjudge.net/problem/POJ-1679 Given a connected undirected graph, tell if its minimum spa ...
- FZU 2087 统计树边【MST相关】
Problem 2087 统计树边 Accept: 212 Submit: 651 Time Limit: 1000 mSec Memory Limit : 32768 KB Prob ...
- POJ 1679 The Unique MST(次小生成树)
求次小生成树的两种方法. 第一种:Kruskal算法比较好操作.先求一遍最小生成树,然后再记录最小生成树上的边.然后再枚举删去最小生成树上的边,再求最小生成树,如果求出的最小生成树的花费等于第一次最小 ...
- 最小生成树(MST)
最小生成树 包含所有N个节点,N-1条边 没有环 权值之和最小 下图表示一最小生成树,原图于其后面. MST=6 原图 Prim算法 是一种贪心算法,从一个节点出发,找最小边的节点加入. #inclu ...
- BZOJ 1821: [JSOI2010]Group 部落划分 Group【MST】
1821: [JSOI2010]Group 部落划分 Group Time Limit: 10 Sec Memory Limit: 64 MB Description 聪聪研究发现,荒岛野人总是过着群 ...
- Codevs 1519 过路费(Mst+Lca)
1519 过路费 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2,3,-,n. ...
- UVA 1151 Buy or Build MST(最小生成树)
题意: 在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方.另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相 ...
最新文章
- 第七课.Logistic回归算法
- javascript——三元操作符
- python 的标准库模块glob使用教程,主要为glob.glob()使用与glob.iglob()使用
- 第 28 小时项目管理过程实践和案例分析
- 继电器rc吸收电路取值_一文读懂继电器的工作原理以及驱动电路
- PCIe学习笔记(15)--- TLP的ROUTING方式
- 深度学习(32)随机梯度下降十: 手写数字识别问题(层)
- ie浏览器收藏夹位置更改步骤
- MySQL精选 | 枚举类型ENUM的DDL变更测试
- 特斯拉副总裁回应“质量不合格”报道:离谱 已准备起诉
- web.xml的contextConfigLocation作用及自动加载applicationContext.xml
- 《模式分类》原书(中文版)及课后习题答案(英文版)分享
- 超标量、超流水、超线程
- python爬取中央气象台台风网当前台风实况和预报数据
- 音乐计算机锦鲤抄,锦鲤抄 (feat. 银临)
- 一文带你认清云服务器和轻量应用服务器的区别
- android 资源文件类型,命名规则(配置限定符名称),及其加载规则
- 天天淘宝,你却不知道个性化推荐技术...
- Win10重装后无法激活问题解决办法
- iPad Air 3(iPad Air 2019)的主要参数与特性
热门文章
- 江苏省事业单位计算机入面分数线,江苏事业单位进面分数线一览!进面名单有你吗...
- python3学习之路 -- 9.1.4)- 获取yemian内容练习
- 天津地铁3号线领舞华苑板块再飞跃
- python数据建模案例源代码_一个完整的数据分析案例 | 用Python建立客户流失预测模型(含源数据+代码)...
- CGB2202面向对象第8天
- set_input_delay如何使用?
- Web 3浪潮席卷东南亚 越南为何会成为“热点”地区
- BZOJ1707:[Usaco2007 Nov]tanning分配防晒霜
- [转]直播云平台架构如何构建? 附PPT
- 用这个神器玩虚荣/最终荣耀手游,效果秒杀模拟器和手机党