zoukankan      html  css  js  c++  java
  • 洛谷 P1131 [ZJOI2007]时态同步(树形dp,贪心)

    传送门


    解题思路

    唔,我才不要上网课呢

    很显然对于每个节点i,必须保证叶子节点到这个点的传送距离相等,才能保证最终答案都是相等,而最少的增加次数一定就是使距离全部变成其中最大的距离。

    好吧,解释的不清楚。

    如果没听懂,重新用贪心来解释一下。

    先想一下最终距离。设最终距离为d。

    最终的距离一定就等于叶子节点到根节点的距离的最大值。

    设节点u有两个儿子i、j(均为叶子节点),要是它们到根节点的距离相等且等于最终距离,首先必须保证它们到点u距离相等,为了使用最小的次数,这个距离一定就是i和j离点u较远的距离的d1,具体操作就是把另一个点加上(d1-d2),然后再把点u到根节点的距离变成(d-d1),这样就能保证使用最小的次数。

    再推广到节点u有n个儿子(均为叶子节点),很显然,一定要把它们到u的距离全部改为离u点最远的距离d1,然后把其他所有的儿子全部加上一个数,使得它们到点u的距离都变成d1,然后再把u点到根节点的距离变成(d-d1)。

    在推广到节点u有n个儿子(不一定为叶子节点),很显然,在我们已经求出以u为根的子树中的每一个叶子节点到点u的最终距离后,取一个max为d1,把其他的儿子加上(d1-到点u的距离),然后再把点u到根节点的距离变成(d-d1)即可。

    所以按照树形dp的写法,用dp[i]表示以i为根的子树中所有的叶子节点到点i的最终距离是多少,然后可以用dp[v](v为i的儿子)来更新dp[i]的值。

    然后关于答案的求法就是在求dp中(改变距离时)加上。

    好吧,貌似翻车了

    还是看代码吧

    AC代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=500005;
     6 int n,s,c[maxn],p[maxn],cnt,dp[maxn];
     7 long long ans;
     8 struct node{
     9     int v,next,value;
    10 }e[maxn*2];
    11 void insert(int u,int v,int value){
    12     cnt++;
    13     e[cnt].v=v;
    14     e[cnt].value=value;
    15     e[cnt].next=p[u];
    16     p[u]=cnt;
    17 }
    18 void dfs(int u,int fa){
    19     if(u!=s&&c[u]==1){
    20         dp[u]=0;
    21         return;
    22     }
    23     for(int i=p[u];i!=-1;i=e[i].next){//求dp
    24         int v=e[i].v;
    25         if(v==fa) continue;
    26         dfs(v,u);
    27         dp[u]=max(dp[u],dp[v]+e[i].value);
    28     }
    29     for(int i=p[u];i!=-1;i=e[i].next){//求答案
    30         int v=e[i].v;
    31         if(v==fa) continue;
    32         ans+=dp[u]-(dp[v]+e[i].value);
    33     }
    34 }
    35 int main()
    36 {
    37     memset(p,-1,sizeof(p));
    38     cin>>n>>s;
    39     for(int i=1;i<n;i++){
    40         int u,v,value;
    41         scanf("%d%d%d",&u,&v,&value);
    42         insert(u,v,value);
    43         insert(v,u,value);
    44         c[u]++;
    45         c[v]++;//求叶子节点
    46     }
    47     dfs(s,-1);
    48     cout<<ans;
    49     return 0;
    50 }

    //ZJOI2007 Day1 t4

  • 相关阅读:
    2017/8/21
    http://edu.manew.com/ ,蛮牛教育(很少免费),主要是unty3D和大数据方向。适合扫盲
    http://www.narkii.com/club/forum-46-1.html 纳金学习论坛,主要是讨论一些unty3D方面的事情,技术栈比较前沿,
    假装很努力,是年轻人的典型幼稚病。(我也有这种问题,改变就是好事。)
    怎么规划一个零基础学习Unity3D的“方法”或者“流程”?
    http://www.jianshu.com/简书。
    java中重载与重写的区别
    NPM 使用介绍(包管理工具,解决NodeJS代码部署上的很多问题)
    Eclipse常用快捷键
    Maven3在Eclipse上安装插件
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/12441305.html
Copyright © 2011-2022 走看看