UVa 1218 树形DP

 

思路主要是紫书 上的,我在这里说一下建树的细节。

#include <vector>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
using namespace std;
vector<int>  son[10005];
int dp[10005][3];
int vis[10005];
//int have[10005];
const int INF = 1<<29;

void search(int u)
{
	vis[u] = 1;
	dp[u][0] = 0;
	dp[u][1] = 0;
	dp[u][2] = 1;
	if(son[u].empty())
	{
		dp[u][0] = INF;
		return ;
	}
	for(int i = 0; i < son[u].size(); i++)
	{
		if(vis[son[u][i]]) continue;                           //从树根开始向下遍历,一旦这个节点用过了,就不能再用了,否则就会出现遍历一个节点的儿子时遍历到这个节点的父亲的情况	      
		if(!vis[son[u][i]])  search(son[u][i]);
		dp[u][1] += dp[son[u][i]][0];
		dp[u][2] += min(dp[son[u][i]][2], dp[son[u][i]][1]);
	}
	int sum = 0;
	for(int i = 0; i < son[u].size(); i++)
		sum += dp[son[u][i]][0];
	dp[u][0] = sum + dp[son[u][0]][2] - dp[son[u][0]][0];	 
	for(int i = 0; i < son[u].size(); i++)
		dp[u][0] = min(dp[u][0], sum + dp[son[u][i]][2] - dp[son[u][i]][0]);
	return ;
}
		
int main()
{
	//freopen("ztest.txt","r",stdin);
	//freopen("zans.txt","w",stdout);
	int n, root;
	int flagg = 1;
	while(scanf("%d",&n))
	{
		for(int i = 0; i <= n; i++)
			son[i].clear();
		int flag = 1, temp1, temp2;
		memset(vis, 0, sizeof(vis));
		//memset(have, 0, sizeof(have));
		while(scanf("%d",&temp1) && temp1)
		{
			if(flag == 1)
			{
				root = temp1;
				flag = 0;
			}
			if(temp1 == -1)  {flagg = 0; break;}
			scanf("%d",&temp2);
			son[temp1].push_back(temp2);                //这时建立的树中,儿子的儿子中有父亲,vis[]解决了这个问题
			son[temp2].push_back(temp1);                
		}
		search(root);
		//for(int i = 1; i <= n; i++)
		//	printf("%d  %d  %d\n",dp[i][0],dp[i][1],dp[i][2]);
		printf("%d\n",min(dp[root][2], dp[root][0]));
		if(!flagg) break;
	}
	return 0;
}

 



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值