傳送門node
給你一棵樹,每一條邊上最多選一個點,問你選的點數.c++
一開始我是想用黑白點染色的思想來作,就是每一條邊都選擇一個點.git
能夠跑兩邊一遍在乎的時候染成黑,第二遍染成白,取一個最大值.spa
就能夠獲得\(30\)分的高分.code
#include <bits/stdc++.h> #define N 100010 #define M 1010 #define _ 0 using namespace std; int n, tot, ans, add_edge, color[N], head[N]; struct node { int next, to; }edge[N]; int read() { int s = 0, f = 0; char ch = getchar(); while (!isdigit(ch)) f |= (ch == '-'), ch = getchar(); while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar(); return f ? -s : s; } void add(int from, int to) { edge[++add_edge].next = head[from]; edge[add_edge].to = to; head[from] = add_edge; } void dfs(int x, int fx) { if (color[fx] == 0) { color[x] = 1; tot++; } for (int i = head[x]; i; i = edge[i].next) { int to = edge[i].to; if (to == fx) continue; dfs(to, x); } } int main() { n = read(); int point; for (int i = 1, x, y; i < n; i++) { x = read(), y = read(); add(x, y), add(y, x); point = x; } dfs(point, 0); ans = max(ans, tot); memset(color, 0, sizeof (color)); tot = 0, color[0] = 1; dfs(point, 0); cout << max(ans, tot); }
很明顯這樣作是錯誤的.來看這樣一組樣例.
按照上述方法跑出來就是\(5\),顯然答案是\(7\).而後我就是這樣被學長\(hack\)了.blog
而後就問了學長樹形\(DP\).get
咱們設\(dp[i][1/0]\)來表示\(i\)與\(i\)的子樹在\(i\),選仍是不選,時的最大權值.it
而後又由於在\(dp[i][1]\)時他的子節點不能選\(dp[to][1]\).class
在\(dp[i][0]\)時均可以選.咱們就能夠獲得這樣的轉移方程(用\(to\)來表示\(i\)的子節點):hack
\[dp[x][0] += max(dp[to][1], dp[to][0]);\]
\[ dp[x][1] += dp[to][0]; \]
而後就作完了.
#include <bits/stdc++.h> #define N 100010 #define M 50010 #define _ 0 using namespace std; int n, add_edge, head[N]; int dp[M][2]; struct node { int next, to; }edge[N]; int read() { int s = 0, f = 0; char ch = getchar(); while (!isdigit(ch)) f |= (ch == '-'), ch = getchar(); while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar(); return f ? -s : s; } void add(int from, int to) { edge[++add_edge].next = head[from]; edge[add_edge].to = to; head[from] = add_edge; } void dfs(int x, int fx) { dp[x][1] = 1; for (int i = head[x]; i; i = edge[i].next) { int to = edge[i].to; if (to == fx) continue; dfs(to, x); dp[x][0] += max(dp[to][1], dp[to][0]); dp[x][1] += dp[to][0]; } } int main() { n = read(); for (int i = 1, x, y; i < n; i++) { x = read(), y = read(); add(x, y), add(y, x); } dfs(1, 0); cout << max(dp[1][0], dp[1][1]); }