[Solution] Shaoxing No.1 Middle School-7.27-T2

Portal
First of all, we can find a property: if a subtree has no flowers, then the subtree does not bifurcate.
From this we can find that if all the subtrees of a point become chains, the number of flowers that need to be hung is -1.
With this tree DP, choose a point as the root, the root is to hang flowers, DP gives the answers to all points.
But if the root is different, the answer may be different.
So enumerating all points as roots, O(n)O(n)O(n) O (n) runs DP
Complexity is O(n2)O(n^2)O(n2)
No, consider optimizing root-changing operations
It's a wonderful technique.
When choosing a point as the root, first count the answers that he takes as the root, then pass his data to his son, and then do DP with his son as the root.
It's not clear. Look at the code.
Code:

#include <bits/stdc++.h>
#define maxn 1000010
using namespace std;
struct Edge{
	int to, next;
}edge[maxn << 1];
int num, head[maxn], dp[maxn], n, ans;

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48) ;
	return s * w;
} 

void addedge(int x, int y){ edge[++num] = (Edge) { y, head[x] }; head[x] = num; }

void dfs1(int u, int pre){//Deal with 1-based answers
	int cnt = 0;
	for (int i = head[u]; i; i = edge[i].next){
		int v = edge[i].to;
		if (v != pre){
			dfs1(v, u);
			dp[u] += dp[v];
			cnt += !dp[v];
		}
	}
	dp[u] += max(cnt - 1, 0);
}

void dfs2(int u, int pre){
	int sum = 0, cnt = 0;
	for (int i = head[u]; i; i = edge[i].next){//Calculate the answer based on the current point
		int v = edge[i].to;
		sum += dp[v];
		cnt += !dp[v];
	}
	ans = min(ans, 1 + (sum += max(cnt - 1, 0)));
	for (int i = head[u]; i; i = edge[i].next){
		int v = edge[i].to;
		if (v != pre){
			dp[u] = sum - dp[v];//Change roots, subtract contributions from points that are about to become roots
			if (!dp[v] && cnt > 1) --dp[u];/
			dfs2(v, u);
		}
	}
}

int main(){
	n = read();
	if (n == 1) return puts("0"), 0;
	for (int i = 1; i < n; ++i){
		int x = read(), y = read();
		addedge(x, y); addedge(y, x);
	}
	dfs1(1, 0);
	ans = n;
	dfs2(1, 0);
	printf("%d\n", ans);
	return 0;
}

Posted by florida_guy99 on Wed, 31 Jul 2019 04:48:29 -0700