令len[x]表示特殊点(即要去的地方)到u的距离。
那么从u出发 走完所有特殊点所需要的代价是 2[sigma(len[x])]-max(len[x])
令dp[u]表示从小到上,特殊点到u的距离和。我们如果从1出发,sigma(len[x])就可以通过一次dfs求得。我们令sum表示距离和。
当1的子节点为根节点的时候,假设为u。当u的子树有特殊点,sum-=2wi。当u除了子树外,还有特殊点,sum+=2*wi。
接着我们计算max(len[x])。这个就是树上任意一点,其他点到这个点的最长距离。我们利用记录最大值和次大值dp来解决这个问题。
令maxx[u]表示u的子树中,到u的最长距离。maxx2[u]表示次长距离。令nxt[u]表示u的最长距离链上,u的直接子节点。
同样,因为特殊点可能在u的子树之外,所以令famax[u]表示,u向上走的最大距离。
对于u的任意一个子节点v,我们可以得到一个dp表达式:
if(v==nxt[u])famax[v]=max(famax[u]+wi,maxx2[u]+wi)
else famax[v]=max(famax[u]+wi,maxx[u]+wi)。
故我们求得 1为根节点后,max和sigma值可以根据1节点的答案dp出来。
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<set> #include<bitset> #include<map> //#include<regex> #include<cstdio> #pragma GCC optimize(2) #define up(i,a,b) for(int i=a;i<b;i++) #define dw(i,a,b) for(int i=a;i>b;i--) #define upd(i,a,b) for(int i=a;i<=b;i++) #define dwd(i,a,b) for(int i=a;i>=b;i--) //#define local typedef long long ll; typedef unsigned long long ull; const double esp = 1e-6; const double pi = acos(-1.0); const int INF = 0x3f3f3f3f; const int inf = 1e9; using namespace std; ll read() { char ch = getchar(); ll x = 0, f = 1; while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } typedef pair<int, int> pir; #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lrt root<<1 #define rrt root<<1|1 const int N = 5e5 + 10; ll dp[N]; ll ffmax[N], ssmax[N], nxt[N], anx[N], famax[N]; int n, k; struct node { ll to, next, wi; }edge[N<<1]; int head[N << 1]; int cnt; int sz[N], fa[N]; ll ans[N]; void addedge(ll u, ll v, ll w) { edge[cnt].to = v; edge[cnt].wi = w; edge[cnt].next = head[u]; head[u] = cnt++; } void dfs1(int u, int f) { fa[u] = f; ll temp = 0; for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == f)continue; dfs1(v, u); sz[u] += sz[v]; if (sz[v]) { dp[u] += dp[v] + 2 * edge[i].wi; if (ffmax[v] + edge[i].wi > temp) { temp = ffmax[v] + edge[i].wi; ssmax[u] = ffmax[u]; ffmax[u] = temp; nxt[u] = v; } else ssmax[u] = max(ssmax[u], ffmax[v] + edge[i].wi); } } } void dfs2(int u) { for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa[u])continue; if (k - sz[v]) { if (v == nxt[u]) { famax[v] = max(famax[u], ssmax[u]) + edge[i].wi; } else { famax[v] = max(famax[u], ffmax[u]) + edge[i].wi; } } ans[v] = ans[u]; if (sz[v])ans[v] -= 2 * 1ll * edge[i].wi; if (k - sz[v])ans[v] += 2 * 1ll * edge[i].wi; dfs2(v); } } int main() { memset(head, -1, sizeof(head)); n = read(), k = read(); ll u, v, w; up(i, 0, n - 1) { u = read(), v = read(); w = read(); addedge(u, v, w); addedge(v, u, w); } up(i, 0, k) { u = read(); sz[u]++; } dfs1(1, 0); ans[1] = dp[1]; dfs2(1); upd(i, 1, n) { printf("%lld\n", ans[i] - max(famax[i], ffmax[i])); } return 0; }
来源:https://www.cnblogs.com/LORDXX/p/12427292.html