LA 2038 Strategic game(二分图最小顶点覆盖 /树形DP)

题意:

给定一棵树,选择尽量少的点,使得每条边至少有一个点被选中。

分析:

做这题的时候看的训练指南上的翻译,想了一下午都不会做,没想到居然翻译是错的~~
其实这题还是很简单的。是UVa10859放置街灯那题的简化版。
dp[i][j]表示节点i状态是j的最优解(j==1表示被选中,0表示不被选中)
然后在树上搜一遍就好。
状态转移方程:

   if(j)ans+=min(dp(v,0,i),dp(v,1,i));//父结点选了,子结点可选可不选
    else ans+=dp(v,1,i); //父结点没选,子结点必须选

其实这题还是二分图最小顶点覆盖的入门题,匈牙利模板跑一下就好,很简单就不写了,可以看看这个: http://blog.csdn.net/u014028317/article/details/45585057

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int INF = 1e9 + 9;
const int N = 1e4+ 9;
int d[N][2];
vector<int>g[N];
int dp(int i,int j,int f)
{
    int& ans=d[i][j];
    if(ans>=0)return ans;
    if(j)ans=1;
    else ans=0;
    for(int k=0;k<g[i].size();k++){
        int v=g[i][k];
        if(v==f)continue;
        if(j)ans+=min(dp(v,0,i),dp(v,1,i));//父结点选了,子结点可选可不选
        else ans+=dp(v,1,i); //父结点没选,子结点必须选
    }
    return ans;
}
int main() {
    //freopen("f.txt","r",stdin);
    int n,m,a,b;
    while(~scanf("%d",&n)) {
        memset(d,-1,sizeof(d));
        for(int i=0;i<=n;i++)g[i].clear();
        for(int i=0;i<n;i++){
            scanf("%d:(%d)",&a,&m);
            while(m--){
                scanf("%d",&b);
                g[a].push_back(b);
                g[b].push_back(a);
            }
        }
        printf("%d\n",min(dp(0,0,-1),dp(0,1,-1)));
    }
    return 0;
}
/*
Sample Input

4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)

Sample Output

1
2
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值