设为首页 加入收藏

TOP

树形DP解决树上的最小点覆盖
2013-09-26 19:51:05 来源: 作者: 【 】 浏览:95
Tags:树形 解决 树上 小点 覆盖

    题目意思:
    给你一棵树
    要你在树上的一些点上放置士兵,放的节点上面是一个
    问你怎样放最少的能使所有的边被照顾到,一个士兵可以同时照顾和他所处节点相连的边
    解题思路:
    最少点覆盖问题
    可以用树形DP解决
    我们把无根树抽象成一棵有根树,0为树根
    对于任意一个节点i来说,设dp[i][0]表示在该节点不放士兵
    dp[i] 表示在该节点放置士兵
    那么结合他的子节点就可以得到状态转移方程
    dp[i] = sum(dp[k][0])+1 k为i的子节点,下同,因为本节点没放,则子节点一定要放
    dp[i][0] = sum( min(dp[k][0],dp[k] ) ) 因为本节点放了,所以取子节点放和不放的最小值
    最后答案就是min( dp[0][0] ,dp[0] )
    虽然是一道很简单的树形DP,但是对与学习树形DP很有启发意义


    下面上代码:
    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;
    const int maxn = 1600;
    int dp[maxn] ;
    int n;
    vector tree[maxn];
    int min(int a,int b)
    {
    return a
    }
    void dfs(int fa,int now)
    {
    dp[now][0] = 0;
    dp[now] = 1;
    int len = tree[now].size();
    int i;
    for(i=0;i
    {
    int t=tree[now][i];
    if(t!=fa)
    {
    dfs(now,t);
    dp[now][0] += dp[t] ;
    dp[now] += min(dp[t][0],dp[t] );
    }
    }
    }
    int main()
    {
    while(~scanf("%d",&n))
    {
    int i;
    for(i=0;i
    {
    tree[i].clear();
    }
    for(i=0;i
    {
    int b;
    int a;
    int j;
    scanf("%d:(%d)",&a,&b);
    for(j=0;j
    {
    int x;
    scanf("%d",&x);
    tree[a].push_back(x);
    tree[x].push_back(a);
    }
    }
    dfs(-1,0);
    cout<
    }
    return 0;
    }

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇关于求最大递增数 下一篇字符串的反转五种方法

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: