zoukankan      html  css  js  c++  java
  • HDU 6741 MUV LUV UNLIMITED (博弈论)

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=6741

    题解

    看完题解深刻地意识到自己是个智障。
    (1) 如果某个叶子节点的父亲有多于一个儿子,则为必胜态。
    证明: 设去掉该叶子后为必败态,则直接删去该点先手必胜;若去掉该叶子后为必胜态,则先手将删去该点之后的必胜策略和这个叶子一同删去,依然是必胜策略。
    (2) 若不存在一个叶子结点父亲有多于一个儿子,考虑每个叶子(含)到深度最大的儿子个数多于(1)的祖先(不含)之间的点数。若所有的这些数都是偶数,那么后手必胜,因为后手可以模仿先手直到存在一个叶子结点父亲有多于一个儿子(也就是某个叶子到深度最大的儿子个数多于(1)的祖先只剩(1)的距离了),从而达到必胜态。否则先手必胜,因为先手可以一步转换为后手必胜状态。
    时间复杂度(O(n)).

    代码

    #include<bits/stdc++.h>
    #define llong long long
    #define mkpr make_pair
    #define riterator reverse_iterator
    using namespace std;
    
    inline int read()
    {
    	int x=0,f=1; char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    	for(; isdigit(ch);ch=getchar()) {x = x*10+ch-'0';}
    	return x*f;
    }
    
    const int N = 1e6;
    int fa[N+3],sonn[N+3];
    int n;
    
    int main()
    {
    	int T = read();
    	while(T--)
    	{
    		n = read();
    		for(int i=2; i<=n; i++) fa[i] = read(),sonn[fa[i]]++;
    		bool ans = false;
    		for(int i=1; i<=n; i++)
    		{
    			if(sonn[i]==0)
    			{
    				if(sonn[fa[i]]>1) {ans = true; break;}
    				int cnt = 1; for(int u=i; sonn[fa[u]]==1; u=fa[u]) {cnt++;}
    				if(cnt&1) {ans = true; break;}
    			}
    		}
    		if(ans==true) puts("Takeru"); else puts("Meiya");
    		for(int i=1; i<=n; i++) fa[i] = sonn[i] = 0;
    	}
    	return 0;
    }
    
  • 相关阅读:
    经典问题的非经典解法
    经典问题之树的深度
    35、AndroidView的滑动方式
    30、Android属性动画
    31、Android矢量动画
    36、AndroidCanvas画布
    27、AndroidEventBus
    28、AndroidRxjava
    32、Android事件分发机制
    29、Android基本动画
  • 原文地址:https://www.cnblogs.com/suncongbo/p/12199866.html
Copyright © 2011-2022 走看看