【51nod】1531 树上的博弈

题解

我们发现每次决策的时候,我们可以判断某个点的决策,至少小于等于几个点或者至少大于等于几个点

我们求最大值
dp[u][1 / 0]
dp[u][1]表示u这个点先手,至少大于等于几个点
dp[u][0]表示u这个点后手走,至少大于等于几个点
转移的时候从dp[u][1]取所有点dp[v][0]最小的那个
dp[u][0]就是所有dp[v][1]的和

最小值
dp[u][1]表示u这个点先手,至少小于等于几个点
dp[u][0]表示u这个点后手,至少小于等于几个点
转移的时候dp[u][0]取所有dp[v][1]最小的那个
dp[u][1]是所有dp[v][1]的和

统计的叶子的时候有个trick就是,一条链的话,根节点点度为1,不算叶子
同时特判只有一个点的情况

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#define enter putchar('
')
#define space putchar(' ')
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
	res = 0;char c = getchar();T f = 1;
	while(c < '0' || c > '9') {
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		res = res * 10 + c - '0';
		c = getchar();
	}
	res *= f;
}
template<class T>
void out(T x) {
	if(x < 0) {putchar('-');x = -x;}
	if(x >= 10) {
		out(x / 10);
	}
	putchar('0' + x % 10);
}
int N,M;
struct node {
	int to,next;
}E[MAXN * 2];
int head[MAXN],sumE,D[MAXN],dp[MAXN][2];
void add(int u,int v) {
	E[++sumE].to = v;
	E[sumE].next = head[u];
	head[u] = sumE;
}
void Init() {
	read(N);
	int u,v;
	for(int i = 1 ; i < N ; ++i) {
		read(u);read(v);add(u,v);add(v,u);
		D[u]++;D[v]++;
	}
	for(int i = 2 ; i <= N ; ++i) {
		if(D[i] == 1) ++M;
	}
}
void dfs1(int u,int fa) {
	int son = 0;
	dp[u][1] = M;dp[u][0] = 0;
	for(int i = head[u] ; i ; i = E[i].next) {
		int v = E[i].to;
		if(v != fa) {
			dfs1(v,u);++son;
			dp[u][1] = min(dp[v][0],dp[u][1]);
			dp[u][0] += dp[v][1];
		}
	}
	if(son == 0) dp[u][1] = dp[u][0] = 1;
}
void dfs2(int u,int fa) {
	int son = 0;
	dp[u][0] = M;dp[u][1] = 0;
	for(int i = head[u] ; i ; i = E[i].next) {
		int v = E[i].to;
		if(v != fa) {
			dfs2(v,u);++son;
			dp[u][1] += dp[v][0];
			dp[u][0] = min(dp[v][1],dp[u][0]);
		}
	}
	if(son == 0) dp[u][1] = dp[u][0] = 1;
}
void Solve() {
	if(M <= 1) {
		out(1);space;out(1);enter;
		return;
	}
	memset(dp,0,sizeof(dp));
	dfs1(1,0);
	out(M - dp[1][1] + 1);space;
	memset(dp,0,sizeof(dp));
	dfs2(1,0);
	out(dp[1][1]);enter;
}
int main() {
#ifdef ivorysi
	freopen("f1.in","r",stdin);
#endif
	Init();
	Solve();
}
原文地址:https://www.cnblogs.com/ivorysi/p/9189146.html