1. 程式人生 > 遊戲 >獵天使魔女2星際火狐零總監參與《街霸6》開發

獵天使魔女2星際火狐零總監參與《街霸6》開發

題面傳送門
這道題好像有兩種做法。
做法一直接無腦上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);
}