题目传送门
题目大意:
看题面吧。
思考过程&具体做法:
很明显我们无法直接求得全局的答案,所以要递归处理每棵子树,用dp[i]代表使i的子树中的所有叶子节点时态同步需要的最小代价,转移方程为dp[i]=
∑dp[j](j为i的儿子)+∑(子树中最远的叶子节点距离−每个儿子的子树中最远的叶子节点距离)
∑
d
p
[
j
]
(
j
为
i
的
儿
子
)
+
∑
(
子
树
中
最
远
的
叶
子
节
点
距
离
−
每
个
儿
子
的
子
树
中
最
远
的
叶
子
节
点
距
离
)
代码:
#include <bits/stdc++.h>
using namespace std;
const long long maxn=5e5+100;
struct stu
{
long long to,next,dis;
}road[2*maxn]; long long first[maxn],cnt=0;
long long n,s;
long long dp[maxn],dis[maxn],fa[maxn];
void addedge(long long x,long long y,long long dis)
{
road[++cnt].to=y;
road[cnt].dis=dis;
road[cnt].next=first[x];
first[x]=cnt;
}
void dfs(long long now,long long dis1)
{
bool flag=0;
for(long long i=first[now];i;i=road[i].next)
{
long long to=road[i].to;
if(to==fa[now]) continue;
fa[to]=now;
flag=1;
dfs(to,dis1+road[i].dis);
dis[now]=max(dis[now],dis[to]);
dp[now]+=dp[to];
}
for(long long i=first[now];i;i=road[i].next)
{
long long to=road[i].to;
if(to==fa[now]) continue;
dp[now]+=(dis[now]-dis[to]);
}
if(!flag)
dis[now]=dis1;
}
int main()
{
scanf("%lld%lld",&n,&s);
for(long long i=1;i<=n-1;i++)
{
long long x,y,dis;
scanf("%lld%lld%lld",&x,&y,&dis);
addedge(x,y,dis);addedge(y,x,dis);
}
dfs(s,0);
printf("%lld\n",dp[s]);
return 0;
}