牛客小白月赛22

链接:https://ac.nowcoder.com/acm/contest/4462/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld 

题目描述

给定一棵树 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
",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
",ans);
117     
118     return 0;
119 }
View Code

重新写了一遍:

 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
",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
",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
",ans);
52     
53     return 0;
54 }

-

原文地址:https://www.cnblogs.com/jiamian/p/12536268.html