点权
题目链接
看完题就知道是换根dp了,哭哭。
就是分两次dfs,
第一次dfs 用儿子节点更新父亲节点
第二次dfs 用父亲节点更新儿子节点
然后这题需要维护最短路/次短路/次次短路
然后,我的wa点在哪里呢?
第二次dfs的时候,当我们用父亲更新儿子的时候,相当于从父亲过来的路径也是当作儿子的一条路径 且 更新——儿子的(最短路 次短路 次次短路)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
#define pb push_back
#define is insert
#define PII pair<int,int>
//mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
//ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
const int N=1e5+50;
const ll INF=0x3f3f3f3f;
const ll MOD=1e9+7;
int n,m;
int d[N];
int head[N];
struct node {
int to,nxt;
ll val;
}e[N<<1];
int idx=0;
void add_edge(int u,int v,ll val){
e[idx]={v,head[u],val};
head[u]=idx++;
}
ll d1[N],d2[N],d3[N];//从以i为根的子树转移上来的最短路 次短路 次次短路
ll p1[N],p2[N];//p1[i]表示 以i为根的子树最短路走到的第一个点
ll rt=1;
ll up[N];
ll dfs_d(int u,int pre){
for(int i=head[u];i!=-1;i=e[i].nxt){
ll v=e[i].to,val=e[i].val;
if(v==pre)continue;
ll d=dfs_d(v,u)+val;
if(d>=INF)continue;
if(d<=d1[u]){
d3[u]=d2[u],d2[u]=d1[u],d1[u]=d;
p2[u]=p1[u],p1[u]=v;
}
else if(d<=d2[u]){
d3[u]=d2[u];d2[u]=d;p2[u]=v;
}
else if(d<d3[u]){
d3[u]=d;
}
}
if(d[u]==1){
d1[u]=0,d2[u]=0,d3[u]=0;
}
if(d2[u]==INF){
return INF;
}
return d1[u]+d2[u];
}
void dfs_u(int u,int pre){
for(int i=head[u];i!=-1;i=e[i].nxt){
ll v=e[i].to,val=e[i].val;
if(v==pre)continue;
ll d;
if(p1[u]==v){
d=d2[u]+d3[u]+val;
}
else if(p2[u]==v){
d=d1[u]+d3[u]+val;
}
else {
d=d1[u]+d2[u]+val;
}
if(d<=d1[v]){
d3[v]=d2[v];d2[v]=d1[v];d1[v]=d;
p2[v]=p1[v];p1[v]=u;
}
else if(d<=d2[v]){
d3[v]=d2[v];d2[v]=d;
p2[v]=u;
}
else if(d<d3[v]){
d3[v]=d;
}
up[v]=min(up[v],d1[v]+d2[v]);
dfs_u(v,u);
}
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++){
d1[i]=d2[i]=d3[i]=INF;
head[i]=-1;
}
for(int i=1;i<n;i++){
ll u,v,val;cin>>u>>v>>val;
add_edge(u,v,val);
add_edge(v,u,val);
d[u]++;d[v]++;
}
if(n==1){
cout<<0;
return ;
}
for(int i=1;i<=n;i++){
if(d[i]>1){
rt=i;
break;
}
}
dfs_d(rt,-1);
for(int i=1;i<=n;i++){
up[i]=d1[i]+d2[i];
if(up[i]>=INF)up[i]=INF;
}
dfs_u(rt,-1);
for(int i=1;i<=n;i++){
// cout<<up[i]<<" ";
if(up[i]<=INF/2)cout<<up[i]<<" ";
else {
cout<<-1<<" ";
}
}
}
signed main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int __=1;//cin>>__;
while(__--){
solve();
}
return 0;
}