トピックリンク:こちらをクリックして壁紙
溶液:
長いタイトル説明は、実際には、リーフノードへのルートからなるように、すべて同じ距離、最小右側を上げる回数を尋ね、あなたのツリーを与えることです
右側の最大距離の最終的な距離を増加させることなく、:非常に明白な結論があります
その後、我々は、設定することができる([X] \ F)\を表す\(X \)ノード\(FA [X] \)側がどのくらいの重量に接続され、プラス
簡単に状態遷移を取得する:\(F [X] =分\ F {[V] | son_xの\でV \} \)
最後に、各点の統計的回答の:\(ANS + = -f [X-] F [FA [X-] \)
長い長い開くには
コード:
//P1131 Treedp
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+1;
const int inf=21474836470000;
int n,rt,cnt,head[N];
int ans,maxdis,dis[N],f[N];
struct Edge{int nxt,to,val;}edge[N<<1];
void ins(int x,int y,int z){
edge[++cnt].nxt=head[x];
edge[cnt].to=y;head[x]=cnt;
edge[cnt].val=z;
}
void getdis(int x,int fa){
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(y==fa) continue;
dis[y]=dis[x]+edge[i].val;
getdis(y,x);maxdis=max(maxdis,dis[y]);
}
}
void dfs(int x,int fa){
f[x]=inf;int flag=0;
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(y==fa) continue;
dfs(y,x);f[x]=min(f[x],f[y]);
flag=1;
}
if(!flag) f[x]=maxdis-dis[x];
}
void calc(int x,int fa){
ans+=f[x]-f[fa];
for(int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(y==fa) continue;
calc(y,x);
}
}
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
signed main(){
n=read(),rt=read();
for(int i=1;i<n;i++){
int x=read(),y=read(),z=read();
ins(x,y,z),ins(y,x,z);
}getdis(rt,0);
dfs(rt,0);calc(rt,0);
printf("%lld\n",ans);
return 0;
}