SDOI2006 保安站岗

树形dp

大水题,直接放代码了qwq(第二位用0 1 2表示三种状态,大力dp就好了)

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<stack>
#include<bitset>
#include<cmath>
using namespace std;
const int maxn=100006;
struct hzw
{
  int to,next,v;
}e[maxn];
int head[maxn],cur,val[maxn];
inline void add(int a,int b)
{
    e[cur].to=b;
    e[cur].next=head[a];
    head[a]=cur++;
}
int n,m,dp[4][maxn];
void dfs(int u,int fa)
{
    int fina=0;dp[2][u]=val[u];
    for (int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        if (v==fa) continue;
        dfs(v,u);
        fina+=min(dp[1][v],dp[2][v]);
        dp[2][u]+=min(min(dp[0][v],dp[1][v]),dp[2][v]);
    }
    dp[0][u]=fina;dp[1][u]=0x3f3f3f3f;
    for (int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        if (v==fa) continue;
        dp[1][u]=min(dp[1][u],fina-min(dp[1][v],dp[2][v])+dp[2][v]);
    }
}
signed main()
{ 
    memset(head,-1,sizeof(head));
    memset(dp,0x3f,sizeof(dp));
    cin>>n;
    for (int i=1,a,b,c,d,e;i<=n;++i)
    {
        scanf("%d%d%d",&a,&b,&c);
        val[a]=b;
//        cout<<a<<" "<<b<<" "<<c<<endl;
        for (int j=1;j<=c;++j)
        {
            scanf("%d",&e);
            add(a,e);
            add(e,a);
        }
    }
    dfs(1,1);
    cout<<min(dp[2][1],dp[1][1]);
}
posted @ 2018-09-11 19:29  Splitor  阅读(99)  评论(0编辑  收藏  举报