【树形DP】观光旅游

  观光旅游

背景

  WZOI 的CJH 教练经常出去旅游 (机房男们那叫一个羡慕啊~~~~~)。当然,CJH 教练的旅游可不是观赏风景那么简单……

问题描述

  CJH 教练预选了N 个城市,打算去这些城市逛逛,并且要拍出一定质量的照片,第i 个城市所能拍出的照片质量为Ci。可是,由于眼光有限,CJH 教练选出的一些城市并不能拍出多少精彩的照片,因此,Ci  可能小于零。N个城市由一些公路连通,每个城市之间有且只有一条路径使其连通。而CJH 教练走的路线比较奇特,在他去的几个城市中,连通任意两个城市的路径上的城市,CJH 教练也都要去过才行 (其实就是要求经过的城市连通)。要知道,拍出的照片可是要在机房中展览的,CJH  教练可不想让机房男嘲笑自己的拍照水准。

鉴于机房男的审美观都不咋的,在好照片中混一些烂照片也不是不可以。CJH  教练有些犯

难,选哪些城市才能让照片总质量最高呢?

  CJH 教练非常看好你,就把这个光荣而艰巨的任务交给你了!

输入格式

  输入数据第1 行有1 个正整数N ,表示城市个数。

  第2 行有N 个整数,第i 个表示在第i 个城市所能拍出的照片质量Ci。

  接下来N – 1 行,每行有两个整数u,v(1≤u,v≤N,u≠v),表示城市u 与城市v 之间有一条公路连接。

输出格式

  输出数据仅一行,要求输出照片的最高总质量。

样例1

photo.in                                photo.ou

5                                       4

-1 1 3 1 -1

4 1

1 3

1 2

4 5

样例2

photo.in                               photo.out

4                                       5

-1 3 1 2

4 1

1 3

1 2

数据规模

对于10%的数据,N≤10,|Ci|≤1000;

对于30%的数据,N≤1000,|Ci|≤2000;

对于50%的数据,N≤10000,|Ci|≤4000;

对于100%的数据,N≤200000,|Ci|≤8000。

时间限制

1s

=======================

===========================

type
  pnode=^node;
  node=record
         x:longint;
         next:pnode;
       end;
var
  n:longint;
  c,s:array[1..200000]of longint;
  tree:array[1..200000]of pnode;
  f_bo{,f_bo1}:array[1..200000]of boolean;
procedure init;
begin
  assign(input,'photo.in');
  assign(output,'photo.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure insert(a,b:longint);
var
  p:pnode;
begin
  new(p);
  p^.x:=b;
  p^.next:=tree[a];
  tree[a]:=p;
end;

procedure dfs(t:longint{;var len:longint});
var
  p:pnode;
 // len1:longint;
begin
  f_bo[t]:=false;
  p:=tree[t];
  while p<>nil do
    begin
      if f_bo[p^.x] then
        begin
          dfs(p^.x{,len1});
          if s[t]+s[p^.x]>s[t] then
            begin
              s[t]:=s[t]+s[p^.x];
              //表示以t为根的树的最大值
              //f_bo1[p^.x]:=true;
              //表示s[t]的最大值是否由p^.x构成..
            end;
        end;
      p:=p^.next;
    end;
end;

procedure main;
var
  i:longint;
  a,b:longint;
  //len:longint;
  ans:longint;
begin
  readln(n);
  for i:=1 to n do
    begin
      read(c[i]);
      tree[i]:=nil;
      s[i]:=c[i];
      //表示以i为根节点的树的最大价值..
    end;
  for i:=1 to n-1 do
    begin
      readln(a,b);
      insert(a,b);
      insert(b,a);
    end;
  fillchar(f_bo,sizeof(f_bo),true);
 // fillchar(f_bo1,sizeof(f_bo1),false);
  dfs(1{,len});
  ans:=s[1];
  {fillchar(f_bo,sizeof(f_bo),true);
  dfs1(1);}
  for i:=2 to n do
    if ans<s[i] then ans:=s[i];
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值