把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

AT3611 Tree MST

题面传送门
这道题好像有两种做法。
做法一直接无脑上Boruvka,然后在树上dp,保存最近的值和和最近值颜色不同的最近值。
但是好难写,不想写怎么办。
考虑MST的一个性质:将边集分成两部分,对两部分分别做MST,然后将两边剩下的边合起来做MST就是现在的MST了。
所以可以考虑淀粉质。
可以确定重心以后算答案,然后两点之间的距离就是两个点到重心的距离和。
所以树内部的边集可以递归下去处理,树之间的边集直接找到\(W_x+D_x\)最小的点让所有点向它连边即可。
然后合并以后跑一遍MST即可。
时间复杂度\(O(n\log^2n)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N (200000+5)
#define M (1<<23)+5
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,k,Si[N+5],vis[N+5],dp[N+5],x,y,z,cnt,Mx,fa[N+5],W[N+5];ll D[N+5],Ans,P[N+5];
I int GF(int x){return fa[x]^x?fa[x]=GF(fa[x]):x;}
struct Edge{int to,w;};vector<Edge> S[N+5];struct Ques{int x,y;ll z;};vector<Ques> E;I bool cmp(Ques x,Ques y){return x.z<y.z;}
I void GS(int x,int La){cnt++;for(Edge i:S[x]) i.to^La&&!vis[i.to]&&(GS(i.to,x),0);}
I void DP(int x,int La){dp[x]=0;Si[x]=1;for(Edge i:S[x]) i.to^La&&!vis[i.to]&&(DP(i.to,x),Si[x]+=Si[i.to],dp[x]=max(dp[x],Si[i.to]));dp[x]=max(dp[x],cnt-Si[x]);dp[x]<dp[Mx]&&(Mx=x);}
I void calc(int x,int La){P[x]=W[x]+D[x];P[x]<P[Mx]&&(Mx=x);for(Edge i:S[x]) i.to^La&&!vis[i.to]&&(D[i.to]=D[x]+i.w,calc(i.to,x),0);}
I void Lk(int x,int La,vector<Ques> &B){B.PB((Ques){x,Mx,P[x]+P[Mx]});for(Edge i:S[x]) i.to^La&&!vis[i.to]&&(Lk(i.to,x,B),0);}
I vector<Ques> Solve(int x,int La){
	cnt=0;GS(x,La);Mx=0;DP(x,La);x=Mx;vis[x]=1;vector<Ques> E,Fs;E.clear();Mx=x;D[x]=0;P[x]=W[x];calc(x,0);Lk(x,0,E);for(Edge i:S[x]){if(vis[i.to])continue;Fs=Solve(i.to,x);
	for(Ques d:Fs) E.PB(d);}Fs=E;sort(Fs.begin(),Fs.end(),cmp);E.clear();for(Ques i:Fs) GF(i.x)^GF(i.y)&&(E.PB(i),fa[GF(i.x)]=GF(i.y));for(Ques i:E) fa[i.x]=i.x,fa[i.y]=i.y;return E; 
}
int main(){
	freopen("1.in","r",stdin);
	RI i;scanf("%d",&n);dp[0]=1e9;for(i=1;i<=n;i++) scanf("%d",&W[i]),fa[i]=i;for(i=1;i<=n;i++) scanf("%d%d%d",&x,&y,&z),S[x].PB((Edge){y,z}),S[y].PB((Edge){x,z});
	E=Solve(1,0);for(Ques d:E) Ans+=d.z;printf("%lld\n",Ans);
}
posted @ 2022-03-01 19:38  275307894a  阅读(46)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end