獵天使魔女2星際火狐零總監參與《街霸6》開發
阿新 • • 發佈:2022-02-22
題面傳送門
這道題好像有兩種做法。
做法一直接無腦上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); }