zoukankan      html  css  js  c++  java
  • 「一本通 5.2 例 5」皇宫看守题解

    题目描述

    太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。

    皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。

    可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。

    帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

    Picture1

    思路:

    做过最大独立集,最小点覆盖,这次终于写到了最小支配集。

    最小支配集是选择最少的点去覆盖所有的点,每个选择的点可以覆盖相连的点和它本身。

    dp方程:

    1.f[pos][0]=min(f[v][0],f[v][2]);

    2.f[pos][1]+=min(f[v][0],f[v][2]);
    3.f[pos][2]+=min(f[v][0],min(f[v][1],f[v][2]));

    1. 可以监控T的子树     不放本身结点
    2. 可以不监控T的子树    不放本身结点
    3. 可以监控T的子树      放本身结点

    所以说第一种情况需要讨论,如果存在f[v][2]被选,就不需要管,因为可以保证pos被v覆盖.

    如果没有f[v][2]被选,就需要在abs(f[v][0]-f[v][2])中选一个最小值,

    来选.

    还有这道题的输入不能搞错....

    代码:

    #include<bits/stdc++.h>
    #define ll long long 
    #define R register
    using namespace std;
    const int N=1e5+85;
    struct E{
      int nxt,to;
    }e[N];
    int n,num,head[N],rot[N],val[N],root=1,f[N][3];
    inline void add(R int u,R int v){
        e[++num].to=v;
        e[num].nxt=head[u];
        head[u]=num;
    }
    // 监控T的子树   不放0  
    // 可以不监控    不放1
    // 监控T的子树   放 2
    inline void dp(R int pos,R int fa){
         f[pos][2]=val[pos];
         R int pd=1,vis=1,cha=0x3f3f3f3f;
         for(R int i=head[pos];i;i=e[i].nxt){
            R int v=e[i].to;
            if(v!=fa){
            pd=0;
            dp(v,pos);
            if(f[v][0]>=f[v][2]){
            f[pos][0]+=f[v][2];
            vis=0;
            }
            else{
            f[pos][0]+=f[v][0];
            cha=min(cha,f[v][2]-f[v][0]);
            }
            f[pos][1]+=min(f[v][0],f[v][2]);
            f[pos][2]+=min(f[v][0],min(f[v][1],f[v][2]));
            }
        }
        if(vis&&pd==0)
        f[pos][0]+=cha;
          if(pd){
        f[pos][0]=val[pos];
        f[pos][1]=0;
        f[pos][2]=val[pos];
        }
    }
    int main(){
        scanf("%d",&n);
        for(R int i=1;i<=n;++i){
            R int p,m,w;
            scanf("%d%d%d",&p,&w,&m);
            val[p]=w;
            for(R int j=1;j<=m;++j){
               R int k;
               scanf("%d",&k);
               add(k,p);add(p,k);
               rot[k]=1;
            }
        }
        while(rot[root])root++;
        dp(root,0);
        printf("%d",min(f[root][0],f[root][2]));
        return 0;
    }
  • 相关阅读:
    2015hust暑假集训 0715 F
    hust2015暑假集训 0715 c a coprime
    0714c
    hdu_1019Least Common Multiple(最小公倍数)
    hdu_1576A/B(扩展欧几里得求逆元)
    hdu_5104 Primes Problem()
    hdu_3483A Very Simple Problem(C(m,n)+快速幂矩阵)
    hdu_2604Queuing(快速幂矩阵)
    hdu_3003Pupu(快速幂)
    神奇的读入读出
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9851914.html
Copyright © 2011-2022 走看看