51nod1531 树上的博弈
Posted ivorysi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1531 树上的博弈相关的知识,希望对你有一定的参考价值。
题解
我们发现每次决策的时候,我们可以判断某个点的决策,至少小于等于几个点或者至少大于等于几个点
我们求最大值
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(‘n‘)
#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();
}
以上是关于51nod1531 树上的博弈的主要内容,如果未能解决你的问题,请参考以下文章