所有边权值和的两倍 - 树直径上边的权值和
树形dp
dp[i][0]:结点i最长枝的长度
dp[i][1]:结点i第二长枝的长度
对所有结点的dp[i][0] + dp[i][1]求最大
#include <cstdio> #include <cstring> using namespace std; #define maxN 100005 int head[maxN], dp[maxN][2]; bool visited[maxN]; int cnt = 0, dmtr = 0; struct Edge { int v, w, next; } edges[maxN - 1]; void addEdge(int u, int v, int w) { edges[cnt].v = v; edges[cnt].w = w; edges[cnt].next = head[u]; head[u] = cnt++; } void treeDp(int root) { visited[root] = true; int fstMax = 0, sndMax = 0; for (int i = head[root]; i != -1; i = edges[i].next) { int v = edges[i].v; if (!visited[v]) { treeDp(v); int curr = dp[v][0] + edges[i].w; if (curr > fstMax) { sndMax = fstMax; fstMax = curr; } else if (curr > sndMax) { sndMax = curr; } } } dp[root][0] = fstMax; dp[root][1] = sndMax; if (fstMax + sndMax > dmtr) dmtr = fstMax + sndMax; } int main(void) { int N, start; int u, v, w; int circum = 0; memset(head, -1, sizeof(head)); memset(visited, 0, sizeof(visited)); memset(dp, 0, sizeof(dp)); scanf("%d%d", &N, &start); for (int i = 0; i < N - 1; i++) { scanf("%d%d%d", &u, &v, &w); circum += w; addEdge(u, v, w); addEdge(v, u, w); } circum *= 2; treeDp(start); printf("%d\n", circum - dmtr); }