• [SDOI2006] 保安站岗


    题目链接

    第一遍不知道为什么就爆零了……

    第二遍改了一下策略,思路没变,结果不知道为什么就 A 了???

    树形 DP 经典问题:选择最少点以覆盖树上所有点(边)。

    对于本题,设 dp[i][0/1][0/1] 表示第 i 个节点,其父亲节点选 / 没选中,且选 / 不选当前节点的最小代价。

    发现选中当前点时,周围的点就爱怎样怎样了,自然是选费用小的……没选中时,如果父亲节点选了那同上;

    如果父亲也没选,那么对于其子节点:

    如果存在一个满足“选择它的代价比不选它的小”,那么一定贪心的选了它,其他的就依然爱怎样怎样了(无情)……

    如果没有这样的一个子节点,那就只好选一个费用差的最小的选了它 233。

    代码:

     1 #include <queue>
     2 #include <cstdio>
     3 #include <cctype>
     4 #include <cstring>
     5 #include <iostream>
     6 #include <algorithm>
     7 using namespace std;
     8 
     9 const int maxn = 1500 + 10;
    10 int n, m, head[maxn], val[maxn], dp[maxn][2][2], edge_num;
    11 
    12 struct Edge { int v, nxt; } edge[maxn << 1];
    13 
    14 inline int read() {
    15   register char ch = 0; register int w = 0, x = 0;
    16   while( !isdigit(ch) ) w |= (ch == '-'), ch = getchar();
    17   while( isdigit(ch) ) x = (x * 10) + (ch ^ 48), ch = getchar();
    18   return w ? -x : x;
    19 }
    20 
    21 inline void Add_edge(int u, int v) {
    22   edge[++edge_num].v = v;
    23   edge[edge_num].nxt = head[u], head[u] = edge_num;
    24 }
    25 
    26 inline void Deep_fs(int x, int p) {
    27   int flag = 0, tmp = 1e8;
    28   for(int i = head[x]; i; i = edge[i].nxt) {
    29     if( edge[i].v == p ) continue;
    30     Deep_fs(edge[i].v, x);
    31     if( dp[edge[i].v][0][0] >= dp[edge[i].v][0][1] ) flag = 1;
    32     dp[x][0][0] = dp[x][0][0] + min(dp[edge[i].v][0][0], dp[edge[i].v][0][1]);
    33     dp[x][0][1] = dp[x][0][1] + min(dp[edge[i].v][1][0], dp[edge[i].v][1][1]);
    34     dp[x][1][0] = dp[x][1][0] + min(dp[edge[i].v][0][0], dp[edge[i].v][0][1]);
    35     dp[x][1][1] = dp[x][1][1] + min(dp[edge[i].v][1][0], dp[edge[i].v][1][1]);
    36   }
    37   if( !flag ) for(int i = head[x]; i; i = edge[i].nxt) {
    38     if( edge[i].v == p ) continue;
    39     tmp = min(tmp, dp[x][0][0] - dp[edge[i].v][0][0] + dp[edge[i].v][0][1]);
    40   }
    41   if( !flag ) dp[x][0][0] = tmp;
    42   dp[x][0][1] = dp[x][0][1] + val[x], dp[x][1][1] = dp[x][1][1] + val[x];
    43 }
    44 
    45 int main(int argc, const char *argv[])
    46 {
    47   freopen("..\nanjolno.in", "r", stdin);
    48   freopen("..\nanjolno.out", "w", stdout);
    49 
    50   scanf("%d", &n);
    51   for(int u, v, k, i = 1; i <= n; ++i) {
    52     u = read(), val[u] = read(), k = read();
    53     for(int j = 1; j <= k; ++j) v = read(), Add_edge(u, v), Add_edge(v, u);
    54   }
    55   Deep_fs(1, 0), printf("%d
    ", min(dp[1][0][0], dp[1][0][1]));
    56 
    57   fclose(stdin), fclose(stdout);
    58   return 0;
    59 }

     —— 花朵以芬芳熏香了空气;但它最终的任务,是把自己献上给你。
        人们从诗人的字句里,选取自己心爱的意义:但是诗句的最终意义, 是指向着你。

  • 相关阅读:
    网站备份list
    vnc checklist
    appnode iptables 规则后面覆盖前面的
    Appnode + Discuz checklist
    解决WORD文档无法显示链接的图像问题
    应用容器Application container
    要研究的内容
    转 Flex MXML编译成AS类
    Flex文件结构
    int a
  • 原文地址:https://www.cnblogs.com/nanjoqin/p/10078325.html
Copyright © 2020-2023  润新知