• [USACO08JAN]Cell Phone Network


    题目大意:
      给你一个n个结点的树,请你搞一些破坏。
      你可以选择手动弄坏某个点,那么与它直接相连的点也会自动坏掉。
      问你把整棵树搞坏至少要手动弄坏几个点?

    思路:
      f[0~2][i]表示不同状态下以i为根的子树至少要手动弄坏几个点。
      我们可以把点的不同状态分为以下三种:
        0:它的孩子有被手动弄坏的。
        1:它自己被手动弄坏。
        2:它父母被手动弄坏。
      设当前根为x,枚举每个孩子y,一个固定的手动弄坏的孩子z,转移方程如下:
        f[0][x]=sum{min(f[0][y],f[1][y])|y≠z}+f[1][z];
        f[1][x]=sum{min(f[0][y],f[1][y],f[2][y])}+1;
        f[2][x]=sum{min(f[0][y],f[1][y])};
      最后答案为min(f[0][1],f[1][1])。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<vector>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int inf=0x7fffffff;
    12 const int N=10001;
    13 std::vector<int> e[N];
    14 inline void add_edge(const int &u,const int &v) {
    15     e[u].push_back(v);
    16     e[v].push_back(u);
    17 }
    18 int f[3][N];
    19 int t[N];
    20 void dp(const int &x,const int &par) {
    21     f[0][x]=inf;
    22     f[1][x]=1;
    23     int tmp=0;
    24     for(register std::vector<int>::iterator i=e[x].begin();i!=e[x].end();i++) {
    25         const int &y=*i;
    26         if(y==par) continue;
    27         dp(y,x);
    28         t[y]=tmp;
    29         tmp+=std::min(f[0][y],f[1][y]);
    30         f[1][x]+=std::min(std::min(f[0][y],f[1][y]),f[2][y]);
    31         f[2][x]+=std::min(f[0][y],f[1][y]);
    32     }
    33     tmp=0;
    34     for(register std::vector<int>::reverse_iterator i=e[x].rbegin();i!=e[x].rend();i++) {
    35         const int &y=*i;
    36         if(y==par) continue;
    37         t[y]+=tmp;
    38         tmp+=std::min(f[0][y],f[1][y]);
    39     }
    40     for(register std::vector<int>::iterator i=e[x].begin();i!=e[x].end();i++) {
    41         const int &y=*i;
    42         if(y==par) continue;
    43         f[0][x]=std::min(f[0][x],t[y]+f[1][y]);
    44     }
    45 }
    46 int main() {
    47     const int n=getint();
    48     for(register int i=1;i<n;i++) {
    49         add_edge(getint(),getint());
    50     }
    51     dp(1,0);
    52     printf("%d
    ",std::min(f[0][1],f[1][1]));
    53     return 0;
    54 }
  • 相关阅读:
    OO第四单元单元总结
    OO第三单元单元总结
    OO第二单元单元总结
    OO第一单元单元总结
    Java虚拟机解释器与编译器
    20155321 《Java程序设计》实验三 敏捷开发与XP实践
    20155321 2016-2017-2 《Java程序设计》第十周学习总结
    20155321 2016-2017-2 《Java程序设计》第九周学习总结
    20155321实验二 Java面向对象程序设计
    20155321 2016-2017-2 《Java程序设计》第八周学习总结
  • 原文地址:https://www.cnblogs.com/skylee03/p/7736881.html
Copyright © 2020-2023  润新知