zoukankan      html  css  js  c++  java
  • p1302

    开学啦!又开始了苦逼的生活,完全没有放假够啊。

    还是来看题吧……

    样例输入 Sample Input 
    6
    10
    20
    25
    40
    30
    30
    4 5
    1 3
    3 4
    2 3
    6 4
    样例输出 Sample Output 
    90

    一道正常的树上dp。

    为什么是树呢?题目中提示的非常清楚了,n个节点n-1条边,每个点都有边,不是树还能是什么?

    为什么是dp呢?假如我知道了子节点们的各种数据,那我可以在很短时间内计算出这个节点的数据,叶子节点的数据还巨好求。

    怎么dp呢?这道题是有一点点后效性的,选与不选都会影响到父节点的选取,那就多一个维度好了,反正不多。

    我们维护ans1[i]表示选取i节点的最大值,ans0[i]表示不选的最大值。选取的时候只能把子节点的ans0加上,但是可以加上自己的权值。ans0就宽松一些,可以选取子节点ans0和ans1最大的那个,但是不能加上自己的权值了。

    在读入边的时候要弄成无向边,那么dfs的时候就要用一个falg数组判断是否经历过了,因为子节点有时候也会指向父节点的。

    using namespace std;
    int i,f,k,tx,ty;
    int n;
    int ans1[100010],ans0[100010],v[100010];
    int tot,link[100010];
    bool flag[100010];
    struct node
    {
        int x,y,next;
    }o[200010];
    void add(int x,int y)
    {
        tot++;
        o[tot].x=x;
        o[tot].y=y;
        o[tot].next=link[x];
        link[x]=tot;
    }
    void dfs(int now)
    {
        flag[now]=1;
        for(int j=link[now];j!=0;j=o[j].next)
        {
            if(flag[o[j].y])continue;
            dfs(o[j].y);
            ans1[now]+=ans0[o[j].y];
            ans0[now]+=max(ans0[o[j].y],ans1[o[j].y]);
        }
        ans1[now]+=v[now];
        return ;
    }
    int main()
    {
    ios::sync_with_stdio(false);
    //freopen("123.in","r",stdin);
    //freopen("123.out","w",stdout);
        cin>>n;
        for(i=1;i<=n;i++)
            cin>>v[i];
        for(i=1;i<n;i++)
        {
            cin>>tx>>ty;
            add(tx,ty);
            add(ty,tx);
        }
        dfs(1);
        cout<<max(ans1[1],ans0[1]);
        return 0;
    }
  • 相关阅读:
    【日语】标日初级上册单词(5-8)1
    【日语】标日初级上册单词(1-4)1
    【日语】计算机日语
    百家姓日语
    【日语】动物名称日语单词集合
    【日语】日语常用会话1000句
    【日语】编程相关日语词汇
    【日语】日语N5学习
    【日语】日语新闻核心词汇
    使用uni-app开发微信小程序之登录模块
  • 原文地址:https://www.cnblogs.com/qywyt/p/9570075.html
Copyright © 2011-2022 走看看