链接:https://ac.nowcoder.com/acm/contest/4462/B
来源:牛客网
题目描述
给定一棵树 T ,树 T 上每个点都有一个权值。
定义一颗树的子链的大小为:这个子链上所有结点的权值和 。
请在树 T 中找出一条最大的子链并输出。
输入描述:
第一行输入一个 n,1≤n≤105。
接下来一行包含n个数,对于每个数 ai,−105≤ai≤105,表示 i 结点的权值。
接下来有n-1行,每一行包含两个数u,v( 1≤u,v≤n , u != v),表示u与v之间有一条边。
输出描述:
仅包含一个数,表示我们所需要的答案。
输入
5 2 -1 -1 -2 3 1 2 2 3 2 4 2 5
输出
4
说明
样例中最大子链为1 -> 2 -> 5
备注:
一个结点,也可以称作一条链
最开始写的有点麻烦(可忽略):

1 #include <stdio.h>
2 #include <string.h>
3 #include <iostream>
4 #include <string>
5 #include <math.h>
6 #include <algorithm>
7 #include <vector>
8 #include <stack>
9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <sstream>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const double eps =1e-8;
16 const int mod=1e9+7;
17 const int maxn=1e5+10;
18 using namespace std;
19
20 struct edge
21 {
22 int to;
23 int next;
24 }E[2*maxn];//注意边的条数
25 int head[maxn];
26 int tot;
27 void add(int u,int v)
28 {
29 E[tot].to=v;
30 E[tot].next=head[u];
31 head[u]=tot++;
32 }
33
34 LL val[maxn];
35 int in[maxn];
36 int out[maxn];
37 LL ans;
38
39 LL DFS(int u,int fa)
40 {
41 if(out[u]==1&&fa!=-1)
42 return val[u]<0? 0:val[u];
43 priority_queue<LL,vector<LL>,greater<LL> > qe;//维护子链返回的两个最大值
44 for(int i=head[u];i!=-1;i=E[i].next)
45 {
46 int v=E[i].to;
47 if(v==fa) continue;
48 LL t=DFS(v,u);
49 if(t>0)
50 {
51 if(qe.size()<2) qe.push(t);
52 else
53 {
54 LL p=qe.top();
55 if(t>p)
56 {
57 qe.pop(); qe.push(t);
58 }
59 }
60 }
61 }
62 LL res=val[u];
63 if(qe.size()==1)
64 {
65 LL t1=qe.top(); qe.pop();
66 ans=max(ans,t1);
67 res+=t1;
68 }
69 else if(qe.size()==2)
70 {
71 LL t1=qe.top(); qe.pop();
72 LL t2=qe.top(); qe.pop();
73 ans=max(ans,t1+t2+val[u]);
74 res+=t2;
75 }
76 return res<0? 0:res;
77 }
78
79
80 int main()
81 {
82 #ifdef DEBUG
83 freopen("sample.txt","r",stdin);
84 #endif
85
86 int n;
87 scanf("%d",&n);
88 ans=-INF;
89 memset(head,-1,sizeof(head));
90 for(int i=1;i<=n;i++)
91 {
92 scanf("%lld",&val[i]);
93 ans=max(ans,val[i]);
94 }
95 if(ans<=0)
96 {
97 printf("%lld\n",ans);
98 return 0;
99 }
100
101 for(int i=1;i<=n-1;i++)
102 {
103 int u,v;
104 scanf("%d %d",&u,&v);
105 add(u,v); add(v,u);
106 in[v]++; in[u]++; out[u]++; out[v]++;
107 }
108 for(int i=1;i<=n;i++)
109 {
110 if(in[i]==1)
111 {
112 ans=max(ans,DFS(i,-1));
113 break;
114 }
115 }
116 printf("%lld\n",ans);
117
118 return 0;
119 }
重新写了一遍:
1 #include <bits/stdc++.h>
2 typedef long long LL;
3 const int INF=0x3f3f3f3f; const LL INFF=0x3f3f3f3f3f3f3f3f;
4 const double eps =1e-8;
5 const int mod=1e9+7;
6 const int maxn=1e5+10;
7 using namespace std;
8
9 LL val[maxn];
10 vector<int> vt[maxn];
11 LL ans;
12
13 LL DFS(int u,int fa)
14 {
15 LL res=val[u];
16 LL max1=-INFF,max2=-INFF;
17 for(int i=0;i<vt[u].size();i++)
18 {
19 int v=vt[u][i];
20 if(v==fa) continue;
21 LL t=DFS(v,u);
22 if(t>0)
23 {
24 if(t>=max1) max2=max1, max1=t;
25 else if(t>max2) max2=t;
26 }
27 }
28 ans=max(ans, val[u]+max(0LL,max1)+max(0LL,max2));
29 res+=max(0LL,max1);
30 return res<=0? 0:res;
31 }
32
33
34 int main()
35 {
36 #ifdef DEBUG
37 freopen("sample.txt","r",stdin);
38 #endif
39
40 int n;
41 scanf("%d",&n);
42 ans=-INFF;
43 for(int i=1;i<=n;i++)
44 {
45 scanf("%lld",&val[i]);
46 ans=max(ans,val[i]);
47 }
48 if(ans<=0)
49 {
50 printf("%lld\n",ans);
51 return 0;
52 }
53
54 for(int i=1;i<=n-1;i++)
55 {
56 int u,v;
57 scanf("%d %d",&u,&v);
58 vt[u].push_back(v);
59 vt[v].push_back(u);
60 }
61 ans=max(ans,DFS(1,-1));
62 printf("%lld\n",ans);
63
64 return 0;
65 }
另一种写法是直接跑两遍DFS就行(类似求树的直径):
1 #include <bits/stdc++.h>
2 typedef long long LL;
3 const int INF=0x3f3f3f3f; const LL INFF=0x3f3f3f3f3f3f3f3f;
4 const double eps =1e-8;
5 const int mod=1e9+7;
6 const int maxn=1e5+10;
7 using namespace std;
8
9 LL val[maxn];
10 vector<int> vt[maxn];
11 LL ans;
12 int st;
13
14 void DFS(int u,int fa,LL now)
15 {
16 now+=val[u];
17 if(ans<now)
18 {
19 ans=now;
20 st=u;
21 }
22 if(now<0) now=0;
23 for(int i=0;i<vt[u].size();i++)
24 {
25 int v=vt[u][i];
26 if(v==fa) continue;
27 DFS(v,u,now);
28 }
29 }
30
31 int main()
32 {
33 #ifdef DEBUG
34 freopen("sample.txt","r",stdin);
35 #endif
36
37 int n;
38 scanf("%d",&n);
39 ans=-INFF;
40 for(int i=1;i<=n;i++)
41 scanf("%lld",&val[i]);
42 for(int i=1;i<=n-1;i++)
43 {
44 int u,v;
45 scanf("%d %d",&u,&v);
46 vt[u].push_back(v);
47 vt[v].push_back(u);
48 }
49 DFS(1,-1,0);
50 DFS(st,-1,0);
51 printf("%lld\n",ans);
52
53 return 0;
54 }
-
来源:https://www.cnblogs.com/jiamian/p/12536268.html
