zoukankan      html  css  js  c++  java
  • 洛谷 P2458 [SDOI2006]保安站岗

    题目传送门

    解题思路:

    树形DP

    可知一个点被控制有且仅有一下三种情况:

    1、被父亲节点上的保安控制

    2、被儿子节点上的保安控制

    3、被当前节点上的保安控制

    我们设dp[0/1/2][u]表示u节点所在子树中全部被控制的最小代价,0表示只有u节点尚未被控制(等待被其父亲节点控制);

    1表示u节点已经被控制,但u节点上没有保安,所以不能去控制其父亲节点;2表示u节点上有保安

    (机房的神犇说多维数组要把小的那一维写在前面,因为可以优化常数,原理请自行翻阅一本通)

    转移:(以下设v是u的儿子节点)

    dp[0][u]=∑min(dp[1][v],dp[2][v]) i节点上反正没有保安,那么儿子节点只要保证全部控制即可,显然1,2状态都是满足的

    dp[1][u]=∑min(dp[1][v],dp[2][v]) + 某一个dp[2][v] 也就是说对于其中一个儿子取dp[2][v]而其他儿子取min(dp[1][v],dp[2][v])意为i号点必须要找一个儿子来覆盖它,其余随意。这个地方涉及到了算法复杂度的问题,楼下有些题解在这里写的是O(n^2)的转移,但实际上完全可以做到O(n)。具体在代码中细讲。

    dp[2][u]=∑min(dp[0][v],dp[1][v],dp[2][v])+val[u] 这个就简单了,i号点上反正有保安了,所有儿子节点都无所谓了,全部可以转移。

    AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 
     6 using namespace std;
     7 
     8 int n,a[1502],k,m,f[1502][3];
     9 vector<int> l[1502];
    10 
    11 inline void dfs(int root,int fa) {
    12     bool flag = 0;
    13     int sum = 0,_min = 0x3f3f3f3f,id = 0;
    14     f[root][2] = a[root]; 
    15     f[root][1] = f[root][0] = 0;
    16     for(int i = 0;i < l[root].size(); i++) {
    17         if(fa == l[root][i]) continue;
    18         dfs(l[root][i],root);
    19         f[root][0] += min(f[l[root][i]][1],f[l[root][i]][2]);//被父亲保 
    20         f[root][1] += min(f[l[root][i]][1],f[l[root][i]][2]);//被儿子保 
    21         if(f[l[root][i]][1] > f[l[root][i]][2]) flag = 1;
    22         else _min = min(_min,f[l[root][i]][2] - f[l[root][i]][1]);
    23         f[root][2] += min(f[l[root][i]][1],min(f[l[root][i]][2],f[l[root][i]][0]));//自保 
    24     }
    25     if(!flag)
    26         f[root][1] += _min;
    27 }
    28 
    29 int main() {
    30     scanf("%d",&n);
    31     for(int i = 1;i <= n; i++) {
    32         scanf("%d%d%d",&k,&a[i],&m);
    33         for(int j = 1;j <= m; j++) {
    34             int x;
    35             scanf("%d",&x);
    36             l[k].push_back(x);
    37             l[x].push_back(k);
    38         }
    39     }
    40     memset(f,0,sizeof(f));
    41     dfs(1,-1);
    42     printf("%d",min(f[1][1],f[1][2]));
    43     return 0;
    44 } 
  • 相关阅读:
    Java中抽象类和接口的区别(abstract class VS interface)
    ECUST_Algorithm_2019_4
    ECUST_Algorithm_2019_3
    杂题
    ECUST_Algorithm_2019_2
    Magolor的数据结构作业
    ECUST_Algorithm_2019_1
    atcoder 泛做
    2018中国大学生程序设计竞赛
    UVA
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/12215755.html
Copyright © 2011-2022 走看看