裸树形dp
#include <STDIO.H>
#include <STRING.H>
const int MAXN = 50000;
struct node
{
int to, next, val;
}edge[MAXN*2];
int head[MAXN];
int tol;
int fst_max[MAXN];
int sec_max[MAXN];
int fst_num[MAXN];
int sec_num[MAXN];
int path[MAXN]; //该结点为根的子树中,包含该结点的最长路径长度
int num[MAXN]; //最长路径的长度
void add(int u, int v, int w)
{
edge[tol].to = v;
edge[tol].val = w;
edge[tol].next = head[u];
head[u] = tol++;
edge[tol].to = u;
edge[tol].val = w;
edge[tol].next = head[v];
head[v] = tol++;
}
// 保留一个根节点,其余端节点作为叶子节点
void dfs(int u, int pre)
{
fst_max[u] = sec_max[u] = 0;
fst_num[u] = sec_num[u] = 0;
int i, j;
for (i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (v == pre) continue;
dfs(v, u);
if (fst_max[v] + edge[i].val > fst_max[u])
{
sec_max[u] = fst_max[u];
sec_num[u] = fst_num[u];
fst_max[u] = fst_max[v] + edge[i].val;
fst_num[u] = fst_num[v];
}
else if (fst_max[v] + edge[i].val == fst_max[u])
{
fst_num[u] += fst_num[v];
}
else if (fst_max[v] + edge[i].val > sec_max[u])
{
sec_max[u] = fst_max[v] + edge[i].val;
sec_num[u] = fst_num[v];
}
else if (fst_max[v] + edge[i].val == sec_max[u])
{
sec_num[u] += fst_num[v];
}
}
if (fst_num[u] == 0) // leaf node
{
fst_max[u] = sec_max[u] = 0;
fst_num[u] = sec_num[u] = 1;
path[u] = 0;
num[u] = 1;
return ;
}
int c1 = 0, c2 = 0;
path[u] = num[u] = 0;
for (i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (v == pre) continue;
if (fst_max[u] == fst_max[v] + edge[i].val)
c1++;
else if (sec_max[u] == fst_max[v] + edge[i].val)
c2++;
}
if (c1 >= 2) // first + first
{
int tmp = 0;
path[u] = fst_max[u]*2;
for (j = head[u]; j != -1; j = edge[j].next)
{
int v = edge[j].to;
if (v == pre) continue;
if (fst_max[u] == fst_max[v] + edge[j].val)
{
num[u] += tmp * fst_num[v];
tmp += fst_num[v];
}
}
}
else if (c1 >= 1 && c2 >= 1)
{
path[u] = fst_max[u] + sec_max[u];
for (i = head[u]; i!= -1; i = edge[i].next)
{
int v = edge[i].to;
if (v== pre) continue;
if (fst_max[u] == fst_max[v] + edge[i].val)
{
num[u] += fst_num[v] * sec_num[u];
}
}
}
else
{
path[u] = fst_max[u];
num[u] = fst_num[u];
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int n;
int i;
while (scanf("%d", &n) == 1)
{
int u, v, w;
tol = 0;
memset(head, -1, sizeof head);
for (i = 1; i< n; ++i)
{
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
}
dfs(1, -1);
int ans1 = 0, ans2 = 0;
for (i = 1; i<= n; ++i)
{
if (path[i] > ans1)
{
ans1 = path[i];
ans2 = num[i];
}
else if (path[i] == ans1)
{
ans2 += num[i];
}
}
printf("%d %d\n", ans1, ans2);
}
return 0;
}