ZR #1175. 【线上训练 14】游戏

题目链接:传送门(没买的看不了)

很思维,有点树形dp的影子
显然小Y不会向根节点走,因为小Y的目标是叶子节点,向根节点走一定不优
因此,我们可以对于每个子树进行考虑,设 f [ u ] f[u] f[u]表示小Y的棋子在 u u u时,如果只考虑 u u u节点的子树,那么小D至少需要先操作多少次才能获胜
接下来考虑转移,首先,叶子节点的 f f f值显然为 1 1 1,小D只有先操作才能获胜
然后对于一个节点 u u u,因为小D得要把所有非叶节点都堵上,所以总的操作次数是 ∑ v ∈ s o n u f [ v ] \displaystyle\sum_{v∈son_u}f[v] vsonuf[v]
但是此时与子树中的情况相比,小D可以先多操作一次
因此, f [ u ] = ( ∑ v ∈ s o n u f [ v ] ) − 1 f[u]= (\displaystyle\sum_{v∈son_u}f[v])−1 f[u]=(vsonuf[v])1
那么可以发现,小D获胜当且仅当 f [ 1 ] = 0 f[1]= 0 f[1]=0,最后直接判断即可,复杂度 Θ ( n ) \Theta(n) Θ(n)

#include 
#define A 100010

using namespace std;
int n, f[A], a; vector<int> e[A];
void dfs(int fr) {
	if (!e[fr].size()) {f[fr] = 1; return;}
	for (int i = 0; i < e[fr].size(); i++) {
		int ca = e[fr][i];
		dfs(ca); f[fr] += f[ca];
	}
	if (f[fr]) f[fr]--;
}

int main(int argc, char const *argv[]) {
	cin >> n;
	for (int i = 2; i <= n; i++) scanf("%d", &a), e[a].push_back(i);
	dfs(1); puts(f[1] ? "Y" : "D");
}

你可能感兴趣的:(树形dp,ZROI,博弈)