【luoguP1922】女仆咖啡厅桌游吧

题目背景

v带萌萌的妹妹去玩,妹妹想去女仆咖啡馆,小v想去桌游吧。

妹妹:我问你个问题,答不对你就做我一天的奴隶,答对了就今天我就全部听你的。

v全部都听!?”

妹妹:嘻嘻嘻,你还是回答问题吧!

于是小v为了自己一天的幸福,来向你求助。

题目描述

v所在的世界被规划成了树形结构,每一个节点上都可以建一个女仆咖啡厅或者桌游吧或者什么都不建。在确定点1为根节点之后,规划局要求:对于每一个非叶子的节点i,设它子树(包括自己)中所有的女仆咖啡厅的数量为cafe[i],桌游吧数目为table[i],都有cafe[i]等于table[i]

妹妹的问题是:这颗树最多能放多少个女仆咖啡厅。

输入输出格式

输入格式:

第一行,一个正整数N

第二至N行,每行两个正整数uivi,表示viui有一条边。

输出格式:

只有一行,最多能放的女仆咖啡厅的个数。

 

为了写得方便,设f[i]为以i为根节点的子树最多能建的女仆咖啡厅的数量,L[i]i的叶节点孩子的个数,N[i]i的非叶节点孩子的集合。

 

因为对于每个节点,只有它的叶节点孩子和它自己可以随意建女仆咖啡厅和桌游吧,f[a](aN[i])是确定的,不能改动,所以f[i]=( l[i]+1个点上上能建的女仆咖啡厅的数量+


f[ i 的非叶节点孩子])

 

又因为cafe[i]==table[i],所以在每个节点与其叶节点孩子上最多能建(L[i]+1)/2个女仆咖啡厅。

 

则可以推出动态转移方程为:

 

F[i]={f[a]}+(L[i]+1)/2 (a∈N[i])

 

代码如下:

#include <cstdio>
#include <vector>

std::vector<int> con[100001];
int d[100001],s,t,n;
void push(int s,int t){ //怪异的邻接表 
	con[s].push_back(t);
}
int check(int x,int f) //DP函数 
{
	int tot=0,Ttot=1;
	for(int k=0;k<con[x].size();k++){
		int i=con[x][k];
		if(i==f)continue; //如果是x的父节点就返回 
		if(con[i].size()==1)Ttot++; //如果是叶节点就记录 
		else tot+=check(i,x);  //否则加上f[i] 
	}
	return tot+Ttot/2; 
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<n;i++) scanf("%d%d",&s,&t),push(s,t),push(t,s);
	printf("%d",check(1,0));
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值