P8207-[THUPC2022 初赛]最小公倍树【Kruskal】
生活随笔
收集整理的這篇文章主要介紹了
P8207-[THUPC2022 初赛]最小公倍树【Kruskal】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P8207
題目大意
有編號為[L,R][L,R][L,R]區(qū)間的點,連接兩個點x,yx,yx,y邊權的為LCM(x,y)LCM(x,y)LCM(x,y),求這張圖的最小生成樹。
1≤L≤R≤106,R?L≤1051\leq L\leq R\leq 10^6,R-L\leq 10^51≤L≤R≤106,R?L≤105
解題思路
我們有一個結論: 對于張圖GGG中的一個生成子圖EEE,EEE之中的一條邊kkk如果不在EEE最小生成樹中,那么kkk肯定也不在GGG的最小生成樹中。
那么我們考慮找一些可能是答案的邊出來跑最小生成樹。
對于一個iii我們提取出所有它倍數(shù)的點,對于點ikikik來說它肯定不會去連接某個ik′ik'ik′如果存在另一個更小的ik′′ik''ik′′的話,因為這條邊顯然不在這張圖的最小生成樹中。
所以我們可以對于一個點xxx的每個約數(shù)ddd,我們只連接一個最小的d×kd\times kd×k,然后把這些邊拿出來跑KruskalKruskalKruskal就好了。
時間復雜度:O(nlog?2n)O(n\log^2 n)O(nlog2n)
code
#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; }總結
以上是生活随笔為你收集整理的P8207-[THUPC2022 初赛]最小公倍树【Kruskal】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 25岁适合用的眼霜
- 下一篇: 中国冬奥会历史奖牌数量最好排名