CF915F Imbalance Value of a Tree
阿新 • • 發佈:2020-12-31
題面傳送門
考慮如果是邊權怎麼做。那麼對於每個邊從大到小合併然後按次計算貢獻即可。
但是這道題是點權。
就有一個方法是把一條邊的邊權看作兩點權最大值。仔細想想就發現是正確的。
程式碼實現:
#include<cstdio> #include<algorithm> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) using namespace std; int n,m,k,x,y,z,f[1000039],siz[1000039],w[1000039],un,wn; long long ans; inline void read(int &x){ char s=getchar();x=0; while(s<'0'||s>'9') s=getchar(); while(s>='0'&&s<='9') x=x*10+s-48,s=getchar(); } struct yyy{int x,y,z;}s[1000039]; inline bool cmp(yyy x,yyy y){return x.z<y.z;} inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);} int main(){ // freopen("1.in","r",stdin); register int i; read(n);m=n-1; for(i=1;i<=n;i++) read(w[i]); for(i=1;i<=m;i++)read(s[i].x),read(s[i].y),s[i].z=max(w[s[i].x],w[s[i].y]); sort(s+1,s+m+1,cmp); for(i=1;i<=n;i++) f[i]=i,siz[i]=1; for(i=1;i<=m;i++) { un=find(s[i].x);wn=find(s[i].y); ans+=(long long)s[i].z*siz[un]*siz[wn]; f[un]=wn,siz[wn]+=siz[un]; } for(i=1;i<=m;i++)s[i].z=min(w[s[i].x],w[s[i].y]); sort(s+1,s+m+1,cmp); for(i=1;i<=n;i++) f[i]=i,siz[i]=1; for(i=m;i;i--) { un=find(s[i].x);wn=find(s[i].y); ans-=(long long)s[i].z*siz[un]*siz[wn]; f[un]=wn,siz[wn]+=siz[un]; } printf("%lld\n",ans); }