所有边权值和的两倍 - 树直径上边的权值和
树形dp
dp[i][0]:结点i最长枝的长度
dp[i][1]:结点i第二长枝的长度
对所有结点的dp[i][0] + dp[i][1]求最大
#include
#include
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);
}