R - 部门聚会

小Hi在Hihoole公司的实习期结束了。在回学校前,他决定请部门所有同事来住所聚会。  

已知小Hi一共有N名同事,编号1~N,其中第i名同事的酒量是Ai。

这N名同事的上下级关系恰好组成一棵树型结构。对于第i名同事来说,如果他的直接上级没有出席聚会,他会喝掉Ai单位的酒;如果他的直接上级出席了聚会,他会有所收敛,只喝掉Ai/2单位的酒。  

小Hi想知道,自己至少要准备多少单位的酒,才能保证无论哪些人出席聚会,酒都够喝。

Input

第一行包含一个整数N。(1 <= N <= 100000)  

第二行包含N个整数,A1, A2, ... AN。(0 <= Ai <= 100000)    

以下N-1行每行包含两个整数u和v,代表u是v的直接上级。

Output

小Hi至少需要准备的酒量,保留1位小数。

Sample Input

5
5 2 4 1 4
2 4
2 1
1 5
1 3

Sample Output

10.5

第一次做树形DP,寻找父亲节点和子节点的关系,DFS整颗树,进行DP;

ps:先寻找根节点ROOT 从ROOT处一直DFS到叶子节点,自底向上,寻找关系,最后到f[root];

这是最简单的树形DP,比水题还简单,好像,我还没真正体会到真谛。

#include <iostream>
#include <vector>
#include <string>
#include <bits/stdc++.h>
using namespace std;
int a[100005];
int degree[100005];
double f[100005][2];  //0代表不取,1代表取
vector<int> gr[100005];

void dfs(int u)        //搜索
{
    int len=gr[u].size();
    f[u][1]=a[u]*1.0;
    for(int i=0;i<len;i++)
    {
        dfs(gr[u][i]);       
        f[u][0]+=max(f[gr[u][i]][0],f[gr[u][i]][1]);
        f[u][1]+=max(f[gr[u][i]][1]-a[gr[u][i]]*0.5,f[gr[u][i]][0]);
    }
}
int main()
{
    cin.tie(0);
    memset(f,0,sizeof(0));
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        //degree[i]=-1;
    }
	for(int i=1;i<n;i++)//记录入度和子节点
    {
        int x,y;
        cin>>x>>y;
        gr[x].push_back(y);
        degree[y]++;
    }
    
    int root;           
    for(int i=1;i<=n;i++)
        if(degree[i]==0)//寻找根
    {
        root=i;
        dfs(root);
        //break;
    }
    printf("%.1f\n",max(f[root][0],f[root][1]));
    return 0;
    // cout<<max(f[root][0],f[root][1])<<endl;
}

发布了97 篇原创文章 · 获赞 3 · 访问量 9451

猜你喜欢

转载自blog.csdn.net/foolishpichao/article/details/96573256
R
R: