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

    题目链接:https://www.luogu.org/problemnew/show/P2458

    看到题目之后——果断树形DP啊!!

    但是怎么树形DP啊qwq。。。。开始想的是(dp[i][0/1])来表示i节点选不选择。

    那么状态转移方程:

    (dp[i][0]=sum_{v=son(i)}^{}dp[v][1])

    (dp[i][1]=val[i]+sum_{v=son(i)}min(dp[v][0],dp[v][1]))

    然后如果所有小的都是dp[v][0],找一个最小的dp[v][1]加上,然后减去原先对应加上的。

    但是!!这样的写法不对!!

    会被这样一组简单的数据hack掉:

    9
    1 1 1 2
    2 5 3 3 4 5
    3 100 1 6
    4 100 1 7
    5 100 2 8 9
    6 1 0
    7 1 0
    8 1 0
    9 1 0

    为什么呢?是因为我们没有考虑用父亲节点控制该节点的情况

    所以正确的状态设计应该是这样的:

    (dp[i][0])表示节点(i)至少被父亲节点控制。

    (dp[i][1])表示节点(i)至少被子节点控制。

    (dp[i][2])表示节点(i)至少被自己控制。

    那么正确的状态转移方程是:

    (dp[i][0]=sum min(dp[son(i)][1],dp[son(i)][2]))

    (dp[i][1]=sum min(dp[son(i)][1],dp[son(i)][2])+dp[son(i)][2])
    (其中至少有一个是1)

    (dp[i][2]=sum min(dp[son(i)][0],dp[son(i)][1],dp[son(i)][2])+val[i])

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 2010
    using namespace std;
    struct Edge{int nxt,to;}edge[MAXN<<1];
    int edge_number,n,ans=2147483647;
    int val[MAXN],head[MAXN];
    long long dp[MAXN][3];
    void add(int from,int to)
    {
        edge[++edge_number].nxt=head[from];
        edge[edge_number].to=to;
        head[from]=edge_number;
    }
    inline void search(int now,int fa)
    {
        long long sum=0;
        dp[now][2]=val[now];
        for(int i=head[now];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==fa) continue;
            search(v,now);
            dp[now][2]+=min(dp[v][2],min(dp[v][1],dp[v][0]));
            sum+=min(dp[v][1],dp[v][2]);
        }
        dp[now][0]=sum;
        dp[now][1]=2147483647;
        for(int i=head[now];i;i=edge[i].nxt)
        {
        	int v=edge[i].to;
        	if(v==fa) continue;
    		dp[now][1]=min(dp[now][1],sum+dp[v][2]-min(dp[v][1],dp[v][2]));
    	}
        return;
    }
    int main()
    {
        
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int u,w,sum;
            scanf("%d%d%d",&u,&w,&sum);
            val[u]=w;
            for(int j=1;j<=sum;j++)
            {
                int v;
                scanf("%d",&v);
                add(u,v);
                add(v,u);
            }
        }
        memset(dp,0x3f,sizeof(dp));
        search(1,0);
        printf("%lld
    ",min(dp[1][1],dp[1][2]));
        return 0;
    }
    
  • 相关阅读:
    Network (poj1144)
    C. Hongcow Builds A Nation
    ZYB loves Xor I(hud5269)
    D. Chloe and pleasant prizes
    Game(hdu5218)
    约瑟夫环的递推方法
    Misaki's Kiss again(hdu5175)
    Exploration(hdu5222)
    B. Arpa's weak amphitheater and Mehrdad's valuable Hoses
    C. Arpa's loud Owf and Mehrdad's evil plan
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9849108.html
Copyright © 2011-2022 走看看