贪心
开学了。。。
为什么一坨树形DP啊。。。
设 w[x] w [ x ] 为以 x x 为根的子树中传到叶子节点所需时间的最大值。那么每次下传一个标记表示当前已经在这条路径上加了多少时间,每遍历到一个节点时把答案加上 w[rt]−w[x]−rem w [ r t ] − w [ x ] − r e m ,然后把 rem r e m 更新为 w[rt]−w[x] w [ r t ] − w [ x ] 即可。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 500005
#define F inline
using namespace std;
typedef long long LL;
struct edge{ int next,to,dis; }ed[N<<1];
int n,k,rt,h[N],fa[N];
LL ans,w[N],dis[N];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
F int _read(){
int x=0,f=1; char ch=readc();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=readc(); }
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x*f;
}
F void addedge(int x,int y,int z){
ed[++k]=(edge){h[x],y,z},h[x]=k;
}
void dfs(int x){
for (int i=h[x],v;i;i=ed[i].next)
if ((v=ed[i].to)!=fa[x]){
dis[v]=dis[x]+ed[i].dis,fa[v]=x;
dfs(v),w[x]=max(w[x],w[v]);
}
w[x]=max(w[x],dis[x]);
}
void dfs(int x,LL rem){
for (int i=h[x],v;i;i=ed[i].next)
if ((v=ed[i].to)!=fa[x])
ans+=w[rt]-w[v]-rem,dfs(v,w[rt]-w[v]);
}
int main(){
n=_read(),rt=_read();
for (int i=1,x,y,z;i<n;i++)
x=_read(),y=_read(),z=_read(),addedge(x,y,z),addedge(y,x,z);
return dfs(rt),dfs(rt,0),printf("%lld\n",ans),0;
}