洛谷 P3574 [POI2014]FAR-FarmCraft

题目传送门

题目描述

输入输出格式

输入格式:

输出格式:

一行,包含一个整数,代表题目中所说的最小时间。

输入输出样例

样例输入

1 6
2 1 8 9 6 3 2
3 1 3
4 2 3
5 3 4
6 4 5
7 4 6
View Code

样例输出

1 11
View Code

提示

 分析

我们设f[x]为遍历完以x为根的子树且将这棵子树上所有的电脑都安装完毕最终又回到x的最小安装时间

对于一棵子树,根节点所需要的安装时间自然是它本身的价值

那么各个子节点的价值可以直接拿来用吗?显然是不可以的

因为你从根节点遍历到子节点需要花费时间

所以这时就有遍历优先级的问题了

我们是先遍历安装时间最长的子树吗?这样是不可以的,比如下面这幅图

 那我们该怎么办呢,我们可以发现,

代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1000005;
 8 struct Edge{
 9     int next,to;
10 }e[maxn];
11 int head[maxn],len;
12 void Ins(int a,int b){
13     e[++len].to=b;e[len].next=head[a];head[a]=len;
14 }
15 struct Node{
16     int f,siz;
17     Node(){}
18     Node(int a,int b){f=a,siz=b;}     
19     bool operator < (const Node&A)const{
20         return f-siz<A.f-A.siz;
21     }
22 };
23 int dp[maxn],g[maxn],val[maxn],que[maxn];
24 void dfs(int u,int fa){
25     priority_queue<Node> q;
26     if(u-1)dp[u]=val[u];
27     for(int i=head[u];i!=-1;i=e[i].next){
28         int v=e[i].to;
29         if(v==fa)continue;
30         dfs(v,u);q.push(Node(dp[v],g[v]));
31     }
32     while(!q.empty()){
33         Node now=q.top();q.pop();
34         dp[u]=max(dp[u],now.f+g[u]+1);
35         g[u]+=now.siz+2;
36     }
37 }
38 int main(){
39     memset(head,-1,sizeof(head));
40     int n;
41     scanf("%d",&n);
42     for(int i=1;i<=n;i++)
43         scanf("%d",&val[i]);
44     for(int i=1;i<n;i++){
45         int a,b;
46         scanf("%d%d",&a,&b);
47         Ins(a,b);Ins(b,a);
48     }
49     dfs(1,0);
50     printf("%d
",max(dp[1],val[1]+g[1]));
51     return 0;
52 }
View Code
原文地址:https://www.cnblogs.com/liuchanglc/p/12652643.html