题目描述:
大神zcc and zyb(my granddaughter)给定⼀棵n个点的边权树,由于他(她)太强了,所以他想考考你。
求每一个以i为根节点的子树中以i为起点的最长链和次长链是多少?
注: 最长链和次长链必须是彼此没有相同边的两条独立的链。
样例
输入格式
第一行输入一个T(
(
1
<
<
T
)
≤
2
20
(1<<T)≤2^{20}
(1<<T)≤220),表示有T组数据
对于每组数据,输入总共n行 。 第一行有两个整数n和S,分别表示总点数和树根。
第2 ~ n行每行有3个整数x,y,z,表示x到y有一条边,边权为z(
0
<
=
z
<
=
10000
0<=z<=10000
0<=z<=10000)。
输出格式
输出总共
T
∗
2
T*2
T∗2行
对于每组数据,输出两行
第一行输出n个数,第i个数表示以i号点作为根节点的子树的以i为起点的最长链,数之间用2个空格隔开
第二行输出n个数,第i个数表示以i号点作为根节点的子树的以i为起点的次长链,数之间用2个空格隔开
数据规模与约定
%
15
n
<
=
10
\%15 n<=10
%15n<=10 (这是用来给你们找错误的 --by 凉心出题人)
%
25
n
<
=
100
\%25 n<=100
%25n<=100
%
35
n
<
=
500
\%35 n<=500
%35n<=500
%
45
n
<
=
1000
\%45 n<=1000
%45n<=1000
%
55
n
<
=
5000
\%55 n<=5000
%55n<=5000
%
65
n
<
=
10000
\%65 n<=10000
%65n<=10000
%
75
n
<
=
50000
\%75 n<=50000
%75n<=50000
%
100
n
<
=
100000
,
(
1
<
<
T
)
<
=
2
2
0
\%100 n<=100000, (1<<T)<=2^20
%100n<=100000,(1<<T)<=220
注意:对于上述所有输出,行末无空格。
时间限制:1s
空间限制:256MB
分析:
这是一道树形dp的题。
然后这道题目其实有个歧义:就是最长链和次长链是否可以重边。
在这里是不能重边的。
那么我们设:
m
a
x
x
1
[
i
]
maxx1[i]
maxx1[i]表示以i为根的最长链是多少
m
a
x
x
2
[
i
]
maxx2[i]
maxx2[i]表示以i为根的次长链是多少
因为树形dp都是从下往下更新的过程,所以对于一个根x,它的最长链也只与它的儿子有关。
很显然,对于一个根x,它的最长链或者次长链只有通过它儿子的最长链才能更新。
并且它儿子的最长链只能更新它的最长链或者次长链(因为不能有重边,显然它的儿子之间不会有重边)。
那么我们可以推得一下公式:
y
∈
s
o
n
(
x
)
{
m
a
x
x
2
[
x
]
=
m
a
x
x
1
[
x
]
,
m
a
x
x
1
[
x
]
=
m
a
x
x
1
[
y
]
+
e
[
i
]
.
v
(maxx1<maxx1[y]+e[i].v)
m
a
x
x
2
[
x
]
=
m
a
x
x
1
[
y
]
+
e
[
i
]
.
v
(maxx2[x]<maxx1[y]+e[i].v)
y\in son(x) \begin{cases} maxx2[x]=maxx1[x] \ , maxx1[x]=maxx1[y]+e[i].v \text{ (maxx1<maxx1[y]+e[i].v)} \\ maxx2[x]=maxx1[y]+e[i].v \text{ (maxx2[x]<maxx1[y]+e[i].v)} \end{cases}
y∈son(x){maxx2[x]=maxx1[x] ,maxx1[x]=maxx1[y]+e[i].v (maxx1<maxx1[y]+e[i].v)maxx2[x]=maxx1[y]+e[i].v (maxx2[x]<maxx1[y]+e[i].v)
Code
#include<bits/stdc++.h>
using namespace std;
struct node{
int y,v,Next;
}e[200010];
int linkk[100010];
int maxx1[100010];
int maxx2[100010];
int t;
int n,root;
int len=0;
void insert(int x,int y,int v){
e[++len].Next=linkk[x];
linkk[x]=len;
e[len].y=y;
e[len].v=v;
}
void dp(int x,int fa){
for (int i=linkk[x];i;i=e[i].Next){
int y=e[i].y;
if (y==fa) continue;
dp(y,x);
if (maxx1[y]+e[i].v>maxx1[x])
maxx2[x]=maxx1[x],maxx1[x]=maxx1[y]+e[i].v;
else if (maxx1[y]+e[i].v>maxx2[x])
maxx2[x]=maxx1[y]+e[i].v;
}
}
int main(){
freopen("T4.in","r",stdin);
freopen("T4.out","w",stdout);
scanf("%d",&t);
while (t--){
len=0;
scanf("%d %d",&n,&root);
for (int i=1;i<=n;i++) linkk[i]=0,maxx1[i]=0,maxx2[i]=0;
for (int i=1,x,y,z;i<n;i++)
scanf("%d %d %d",&x,&y,&z),insert(x,y,z),insert(y,x,z);
dp(root,0);
printf("%d",maxx1[1]);
for (int i=2;i<=n;i++)
printf(" %d",maxx1[i]);
printf("\n");
printf("%d",maxx2[1]);
for (int i=2;i<=n;i++)
printf(" %d",maxx2[i]);
if (t) printf("\n");
}
fclose(stdin);
fclose(stdout);
}