zoukankan      html  css  js  c++  java
  • 洛谷2458

    f[now][0]表示以当前点为根,且要取该点,满足条件的最小

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int head[1501],to[1501],nex[1501],val[1501],indg[1501],f[1501][3],n,cnt,rt;
    
    inline void read(int &x){
        char ch=getchar();x=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 
    }
    
    void addedge(int u,int v){
        to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt;
    }
    
    void dfs(int now){
        if(!head[now]){f[now][0]=f[now][1]=val[now];f[now][2]=0;return;}
        f[now][0]=val[now];f[now][2]=0;
        for(int i=head[now];i;i=nex[i]){
            dfs(to[i]);
            f[now][0]+=min(f[to[i]][1],min(f[to[i]][2],f[to[i]][0]));
            f[now][2]+=min(f[to[i]][0],f[to[i]][1]);}
        f[now][1]=1e9;
        for(int i=head[now];i;i=nex[i]){
            f[now][1]=min(f[now][1],f[now][2]-min(f[to[i]][0],f[to[i]][1])+f[to[i]][0]);
        }
    }
    
    int main(){
        read(n);
        for(int i=1;i<=n;i++){
            int u,som,v;read(u);read(val[u]);read(som);
            while(som--){read(v);indg[v]++;addedge(u,v);}
        }
        for(int i=1;i<=n;i++)if(!indg[i]){rt=i;break;}
        dfs(rt);
        printf("%d",min(f[rt][0],f[rt][1]));
    }

     
    f[now][1]表示以当前点为根,至少取它的一个儿子,满足条件的最小值
    f[now][2]表示他的儿子均被覆盖,满足条件的最小值
    f[now][0]=val[now]+segma(min(f[son][0~2]));
    f[now][1]=min(f[now][2]-min(f[son][0~1])+f[son][0])
    f[now][2]=segma(f[son][0~1])
    再注意叶子节点的赋值即可

  • 相关阅读:
    BZOJ3196: Tyvj 1730 二逼平衡树
    (转载)你真的会二分查找吗?
    Codeforces Round #259 (Div. 2)
    BZOJ1452: [JSOI2009]Count
    BZOJ2733: [HNOI2012]永无乡
    BZOJ1103: [POI2007]大都市meg
    BZOJ2761: [JLOI2011]不重复数字
    BZOJ1305: [CQOI2009]dance跳舞
    挖坑#4-----倍增
    BZOJ1042: [HAOI2008]硬币购物
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/9021649.html
Copyright © 2011-2022 走看看