树形dp
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld
题目描述
Cwbc和XHRlyb生活在s市,这天他们打算一起出去旅游。
旅行地图上有n个城市,它们之间通过n-1条道路联通。
Cwbc和XHRlyb第一天会在s市住宿,并游览与它距离不超过1的所有城市,之后的每天会选择一个城市住宿,然后游览与它距离不超过1的所有城市。
他们不想住在一个已经浏览过的城市,又想尽可能多的延长旅行时间。
XHRlyb想知道她与Cwbc最多能度过多少天的时光呢?
聪明的你在仔细阅读题目后,一定可以顺利的解决这个问题!
输入描述:
第一行,两个正整数n和s,表示城市个数和第一天住宿的城市s。
接下来n-1行,每行两个整数x和y,表示城市x与城市y之间有一条双向道路。
输出描述:
第一行,一个非负整数表示答案。
备注:
1 ≤ n ≤ 500000, 1 ≤ s, x, y ≤ n。
解题思路
很容易发现n个点n-1条边这就是一棵树,而且给定根节点s,问题目给出的最大值是多少。
很经典的模型,对于根节点选定之后,子节点一定不能选,但是根节点不选子节点可选可不选。那么我们从底层往上递推到根节点即可得到最大值。以为题目要求一定要到s住一晚上,所以最终不用取s点住不住。代表根节点u不住,代表根节点u住一晚上初始化为1。
#pragma GCC target("avx,sse2,sse3,sse4,popcnt") #pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math") #include <bits/stdc++.h> using namespace std; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) #define all(vv) vv.begin(), vv.end() typedef long long ll; typedef unsigned long long ull; typedef long double ld; const ll MOD = 1e9 + 7; inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; } inline void write(ll x) { if (!x) { putchar('0'); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); } inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; } ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } inline int lowbit(int x) { return x & (-x); } const int N = 5e5 + 7; //节点数 const int M = 5e5 + 7; //路径数 const int INF = 0x3f3f3f3f; int head[N], tot = 0;//前向星变量 struct Node { //int u; //起点 //int w; //权值 int v, next; } edge[M << 1]; void add(int u, int v) { tot++; //edge[tot].u = u; edge[tot].v = v; //edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot; } int ans, dp[N][2]; int n, s; void dfs(int x, int fa) { dp[x][1] = 1; for (int i = head[x]; i; i = edge[i].next) { int y = edge[i].v; if (y == fa) continue; dfs(y, x); dp[x][1] += dp[y][0]; dp[x][0] += max(dp[y][0], dp[y][1]); } } int main() { n = read(), s = read(); for (int i = 1; i < n; ++i) { int u = read(), v = read(); add(u, v), add(v, u); } dfs(s, 0); write(dp[s][1]); return 0; }