zoukankan      html  css  js  c++  java
  • hdu6867 Tree // DFS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6867

    大意:给定一棵以1为固定顶点的树,你可以从任意一个父亲节点走到其儿子节点。让你新建一条边,这条边上可以双向通行。求可抵达的点对数,主意node[i]可以抵达自身node[i]。

    这题一上来就想用贪心(是错的),感觉上好像挺对的。找一条最长的路径,看似可以新抵达的点更多。

    实际上此题还与各节点的子树大小具有密切关系。然而我虽然发现了这一点,最后写的搜索竟然TLE。临场还是不行。。第二天写了几分钟就A了。。。

    key:

    考虑不加边: 每个节点可以去到的点的个数即为其自身,以及不包括自身的子树大小。设节点i的后代个数(子树大小-1)为son[i],则这些点对的个数总和就是n + ∑1,n (son[i])

    第一次dfs_son()填满son[]

    考虑加了一条边:首先,加边的点必定位于某条路径的末端与初始根节点1之间,这点显而易见。加边之后,收益增加的点为这条路径上除了1以外的节点。设有k个好了。那对于这k个节点中编号为i的节点,增加的点对则是  n减去包含其自身的子树大小,也即n-1-son[i]。任务就很明确了。

    第二次dfs统计每条路径末端求得的∑(n-1-son[i]),取其中的最大值,再与1中总和相加即为结果

    *转载请附链接 谢谢

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<string>
     5 #include<cstdio>
     6 #include<iomanip>
     7 #include<vector>
     8 #include<queue>
     9 
    10 #define ll long long
    11 using namespace std;
    12 const int maxn = 5e5 + 10;
    13 
    14 int n;
    15 ll ans = 0;
    16 
    17 int son[maxn];
    18 19 
    20 vector<int> v[maxn];
    21 
    22 int dfs_son(int now)
    23 {
    24     int cnt = 0;
    25     ll tmp = 0;
    26     for(int i = 0 ; i < v[now].size() ; i++){
    27         int k = v[now][i];
    28         cnt++;
    29         tmp += dfs_son(k);
    30     }
    31     if(cnt == 0){
    32         son[now] = 1;
    33     }else{
    34         son[now] = tmp + 1;
    35     }    
    36     return son[now];
    37 }
    38 
    39 void dfs_res(int now, bool *vis, ll sum)
    40 {
    41     if(son[now] == 0)    ans = max(ans, sum);
    42     for(int i = 0 ; i < v[now].size() ; i++){
    43         int nxt = v[now][i];
    44         if(vis[nxt] == true)    continue;
    45         vis[nxt] = true;
    46         dfs_res(nxt, vis, sum + n-1-son[nxt]);
    47         vis[nxt] = false;
    48     }
    49     return ;
    50 }
    51 
    52 int main(){
    53     int T;scanf("%d",&T);
    54     while(T--){
    55         scanf("%d",&n);
    56         ans = 0;
    57         for(int i = 0 ; i <= n ; i++){
    58             son[i] = 0;
    59             v[i].clear();
    60         }
    61         
    62         for(int i = 2 ; i <= n ; i++){
    63             int father;
    64             scanf("%d",&father);
    65             v[father].push_back(i);//反向
    66         }
    67         
    68         dfs_son(1);//求每个节点的儿子个数
    69         
    70         ll sum = 0;//所有节点的儿子和 
    71         for(int i = 1 ; i <= n ; i++){
    72             son[i] -= 1;
    73             sum += son[i];
    74         }
    75         
    76         bool vis[maxn];
    77         vis[1] = true;
    78         dfs_res(1, vis, 0);
    79         
    80         ans += sum + n;
    81         printf("%lld
    ",ans);
    82     }
    83         
    84     return 0;
    85 }
  • 相关阅读:
    English,The Da Vinci Code, Chapter 23
    python,meatobject
    English,The Da Vinci Code, Chapter 22
    English,The Da Vinci Code, Chapter 21
    English,The Da Vinci Code, Chapter 20
    English,The Da Vinci Code, Chapter 19
    python,xml,ELement Tree
    English,The Da Vinci Code, Chapter 18
    English,The Da Vinci Code, Chapter 17
    English,The Da Vinci Code, Chapter 16
  • 原文地址:https://www.cnblogs.com/ecustlegendn324/p/13531727.html
Copyright © 2011-2022 走看看