P8207-[THUPC2022 初赛]最小公倍树【Kruskal】

1|0正题

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


1|1题目大意

有编号为[L,R]区间的点,连接两个点x,y边权的为LCM(x,y),求这张图的最小生成树。

1LR106,RL105


1|2解题思路

我们有一个结论: 对于张图G中的一个生成子图EE之中的一条边k如果不在E最小生成树中,那么k肯定也不在G的最小生成树中。

那么我们考虑找一些可能是答案的边出来跑最小生成树。

对于一个i我们提取出所有它倍数的点,对于点ik来说它肯定不会去连接某个ik如果存在另一个更小的ik的话,因为这条边显然不在这张图的最小生成树中。

所以我们可以对于一个点x的每个约数d,我们只连接一个最小的d×k,然后把这些边拿出来跑Kruskal就好了。

时间复杂度:O(nlog2n)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; struct node{ ll x,y,w; }e[11000000]; ll L,R,ans,m,fa[1100000]; bool cmp(node x,node y) {return x.w<y.w;} ll find(ll x) {return (fa[x]==x)?x:(fa[x]=find(fa[x]));} signed main() { scanf("%lld%lld",&L,&R); for(ll i=1;i<=R;i++){ for(ll j=i;j<=R;j+=i){ if(j>=L){ ll p=(L+i-1)/i*i; if(p==j)continue; e[++m]=(node){j,p,j*p/i}; } } } sort(e+1,e+1+m,cmp); for(ll i=L;i<=R;i++)fa[i]=i; for(ll i=1;i<=m;i++){ ll x=find(e[i].x),y=find(e[i].y); if(x==y)continue; ans+=e[i].w;fa[x]=y; } printf("%lld\n",ans); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/16018767.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(183)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-03-17 P4643-[国家集训队]阿狸和桃子的游戏【结论】
2021-03-17 P6076-[JSOI2015]染色问题【组合数学,容斥】
点击右上角即可分享
微信分享提示