牛客小白月賽3 G

lao_kai_ybqy發表於2020-12-01

旅遊

題目連結
考樹形dp

題目描述

連結:https://ac.nowcoder.com/acm/contest/87/G
來源:牛客網

Cwbc和XHRlyb生活在s市,這天他們打算一起出去旅遊。
旅行地圖上有n個城市,它們之間通過n-1條道路聯通。
Cwbc和XHRlyb第一天會在s市住宿,並遊覽與它距離不超過1的所有城市,之後的每天會選擇一個城市住宿,然後遊覽與它距離不超過1的所有城市。
他們不想住在一個已經瀏覽過的城市,又想盡可能多的延長旅行時間。
XHRlyb想知道她與Cwbc最多能度過多少天的時光呢?
聰明的你在仔細閱讀題目後,一定可以順利的解決這個問題!

輸入描述:

第一行,兩個正整數n和s,表示城市個數和第一天住宿的城市s。
接下來n-1行,每行兩個整數x和y,表示城市x與城市y之間有一條雙向道路。

輸出描述

第一行,一個非負整數表示答案。

輸入樣式

4 1
1 2
2 3
3 4

輸出樣式

2

說明

第一天,在1號城市住宿,遊覽了1、2號城市。
第二天,在3號城市住宿,遊覽了4號城市,旅行結束。

演算法分析

樹形dp,算天數f[i][1]=1;f的初始值為1天
f[i][0]=f[j][1];//f[i][0]代表 i 沒來,
f[i][1]=max(f[j][0],f[j][1]);//f[i][1]代表 i 來了的情況下,判斷是沒來天數多還是來了的天數多

程式碼實現

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+5; 
struct edge
{
	int pre,to;
}e[maxn*2];
int head[maxn],f[maxn][2];
int cnt=0;
void add(int x,int y)
{
	e[++cnt].pre=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
void dfs(int x,int y)
{
	for(int i=head[x];i;i=e[i].pre)
	{
		int s=e[i].to;
		if(s==y)	continue;
		dfs(s,x);
		f[x][0]+=max(f[s][1],f[s][0]);
		f[x][1]+=f[s][0];
	}
}
int main()
{
	int n,z;
	cin>>n>>z;
	for(int i=1;i<=n;i++)	
		f[i][1]=1;
	int a,b;
	for(int i=1;i<n;i++)
	{
		cin>>a>>b;
		add(a,b);
		add(b,a);
	}	
	dfs(z,0);
	cout<<f[z][1]<<endl;
	return 0;
}