zoukankan      html  css  js  c++  java
  • POJ 1655 Balancing Act && POJ 3107 Godfather

    题目大意:

    根据题目的图很好理解意思,就是记录每一个点的balance,例如 i 的balance就是把 i 从这棵树中除去后得到的森林中含有结点数最多

    的子树中的节点个数,然后找到所有节点中对应的balance的最小值 , 并输出最小值对应的最小的标号

    题目不要看花。。。前一个是找最大,后面找所有最大值中的最小,我就是看错一直wa,后来人家题解刚看完题目意思就反应过来 , 囧死了 - -

    昨天貌似做过一道类似的题,任意找一点 , 比如 1 作为根进行dfs,第一次dfs记录所有点对应的子树中含有的节点的总个数

    第二次dfs记录down[i] , 也就是i子树中 i 连接的所有子树中含有节点数最多的节点个数

    其实down[i]就相当 i 出去后 , i 下方森林可得到的最大balance , 还需要求一个 i 上方的balance , 这个上方的值就是n-sum[i]

    两者比较取最大就可以了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 const int N = 20005;
     6 int first[N] , k , sum[N] , down[N] , rec[N];
     7 
     8 struct Edge{
     9     int y , next;
    10 }e[N<<1];
    11 
    12 void add_edge(int x , int y)
    13 {
    14     e[k].y = y , e[k].next = first[x];
    15     first[x] = k++;
    16 }
    17 
    18 void dfs1(int u , int fa)
    19 {
    20     sum[u] = 1;
    21     for(int i=first[u] ; i!=-1 ; i=e[i].next)
    22     {
    23         int v = e[i].y;
    24         if(v == fa) continue;
    25         dfs1(v , u);
    26         sum[u] += sum[v];
    27     }
    28 }
    29 void dfs2(int u , int fa)
    30 {
    31     for(int i=first[u] ; i!=-1 ; i=e[i].next)
    32     {
    33         int v = e[i].y;
    34         if(v == fa) continue;
    35         down[u] = max(sum[v]+1 , down[u]);
    36         dfs2(v , u);
    37     }
    38 }
    39 
    40 int main()
    41 {
    42   //  freopen("a.in" , "r" , stdin);
    43     int T;
    44     scanf("%d" , &T);
    45     while(T--)
    46     {
    47         int n , a , b;
    48         scanf("%d" , &n);
    49         memset(first , -1 , sizeof(first));
    50         k = 0;
    51         for(int i=1 ; i<n ; i++){
    52             scanf("%d%d" , &a , &b);
    53             add_edge(a , b);
    54             add_edge(b , a);
    55         }
    56         memset(down , 0 , sizeof(down));
    57         dfs1(1 , -1);
    58         dfs2(1 , -1);
    59         int minn = down[1]-1;
    60         rec[1] = down[1]-1;
    61       //  cout<<"down: 1: "<<down[1]<<" "<<sum[1]<<endl;
    62         for(int i=2 ; i<=n ; i++){
    63         //    cout<<"down: i: "<<i<<" "<<" "<<down[i]<<" "<<sum[i]<<endl;
    64             rec[i] = max(down[i]-1 , n-sum[i]);
    65             minn = min(minn , rec[i]);
    66         }
    67         int i;
    68         for(i=1 ; i<=n ; i++){
    69             if(rec[i] == minn) break;
    70         }
    71         printf("%d %d
    " , i , minn);
    72     }
    73     return 0;
    74 }

     
    POJ 3107

    求解问题的思想是和上面的题目是基本相同的,除了输入输出方式需要改变,然后数组开大点就可以照抄上面代码了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 const int N = 50005;
     6 int first[N] , k , sum[N] , down[N] , rec[N];
     7 
     8 struct Edge{
     9     int y , next;
    10 }e[N<<1];
    11 
    12 void add_edge(int x , int y)
    13 {
    14     e[k].y = y , e[k].next = first[x];
    15     first[x] = k++;
    16 }
    17 
    18 void dfs1(int u , int fa)
    19 {
    20     sum[u] = 1;
    21     for(int i=first[u] ; i!=-1 ; i=e[i].next)
    22     {
    23         int v = e[i].y;
    24         if(v == fa) continue;
    25         dfs1(v , u);
    26         sum[u] += sum[v];
    27     }
    28 }
    29 void dfs2(int u , int fa)
    30 {
    31     for(int i=first[u] ; i!=-1 ; i=e[i].next)
    32     {
    33         int v = e[i].y;
    34         if(v == fa) continue;
    35         down[u] = max(sum[v]+1 , down[u]);
    36         dfs2(v , u);
    37     }
    38 }
    39 
    40 int main()
    41 {
    42   //  freopen("a.in" , "r" , stdin);
    43     int n , a , b;
    44     while(scanf("%d" , &n) == 1){
    45         memset(first , -1 , sizeof(first));
    46         k = 0;
    47         for(int i=1 ; i<n ; i++){
    48             scanf("%d%d" , &a , &b);
    49             add_edge(a , b);
    50             add_edge(b , a);
    51         }
    52         memset(down , 0 , sizeof(down));
    53         dfs1(1 , -1);
    54         dfs2(1 , -1);
    55         int minn = down[1]-1;
    56         rec[1] = down[1]-1;
    57       //  cout<<"down: 1: "<<down[1]<<" "<<sum[1]<<endl;
    58         for(int i=2 ; i<=n ; i++){
    59         //    cout<<"down: i: "<<i<<" "<<" "<<down[i]<<" "<<sum[i]<<endl;
    60             rec[i] = max(down[i]-1 , n-sum[i]);
    61             minn = min(minn , rec[i]);
    62         }
    63         int num = 0;
    64         for(int i=1 ; i<=n ; i++){
    65             if(rec[i] == minn){
    66                 if(num == 0) printf("%d" , i);
    67                 else printf(" %d" , i);
    68                 num++;
    69             }
    70         }
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    Kibana查询说明
    windows下安装python 且 安装pip
    pycharm编辑器,各种设置及配置修改
    用python输出未来时间,递增
    window 下python2.7与python3.5两版本共存设置
    python 运算符
    python 运算及注释
    js 实现动态的图片时钟
    js table的笔记,实现添加 td,实现搜索功能
    js实现图片无缝连接
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4233752.html
Copyright © 2011-2022 走看看