码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 1054 Strategic Game 二分图最小顶点覆盖?树形DP

时间:2015-06-06 16:42:03      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:c   c++   acm   算法   编程   

分析:这里使用树形DP做。

1、最小顶点覆盖做法:最小顶点覆盖 == 最大匹配(双向图)/2。

2、树形DP:
dp[i][0]表示i为根节点,并且该节点不放,所需的最少的点数。
dp[i][1]表示i为根节点,并且该节点放,所需要的最少的点数。

dp[i][0]=sum(dp[son[i][j]][1]) 该点不放,则它的儿子节点必须都放,只有这样之间的边才可以被覆盖。
dp[i][1]=sum(min(dp[son[i][j]][0],dp[son[i][j]][1])) 该点放的话,则它的儿子节点有两种决策,放或不放,取min即可。

#include<iostream>
#include<vector>
#include<limits.h>
using namespace std;

#define N 1505
int dp[N][2];    //dp[i]表示以i为根节点时所需要的最小点数
int f[N];        //用来记录父节点
vector<int> son[N]; //记录儿子节点

int min(int x,int y)
{
	return x<y?x:y;
}

int dfs(int pos,int v)
{
	int sum,i;

	if(dp[pos][v]!=INT_MIN)
		return dp[pos][v];
	sum=v;
	for(i=0;i<son[pos].size();i++)
		if(v==1)                    //当前节点选
			sum+=min(dfs(son[pos][i],0),dfs(son[pos][i],1));
		else
			sum+=dfs(son[pos][i],1);//当前节点不选,子节点必选
	dp[pos][v]=sum;
	return sum;
}

int main()
{
	int ans,n,i,x,m,j,t;

	while(scanf("%d",&n)==1)
	{
		for(i=0;i<n;i++)
		{
			son[i].clear();
			f[i]=i;
			dp[i][0]=dp[i][1]=INT_MIN;
		}
		for(i=0;i<n;i++)
		{
			scanf("%d:(%d)",&x,&m);
			for(j=0;j<m;j++)
			{
				scanf("%d",&t);
				son[x].push_back(t);
				f[t]=x;
			}
		}
		for(i=0;i<n;i++)
			if(f[i]==i)    //找到根节点
			{
				ans=min(dfs(i,0),dfs(i,1));
				break;
			}
		printf("%d\n",ans);
	}
    return 0;
}


HDU ACM 1054 Strategic Game 二分图最小顶点覆盖?树形DP

标签:c   c++   acm   算法   编程   

原文地址:http://blog.csdn.net/a809146548/article/details/46388739

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!