zoukankan      html  css  js  c++  java
  • 【洛谷P4096】Eden 的博弈树

    题目

    题目链接:https://www.luogu.com.cn/problem/P4096

    思路

    (f[x][0/1]) 表示如果要确定点 (x) 是必败 / 必胜的话至少要确定多少个叶子。那么枚举子节点 (v),有

    [f[x][0]=sum_{vin son[x]}f[v][1] ]

    [f[x][1]=min_{vin son[x]}(f[v][0]) ]

    然后求出来 (f[1]) 后再次分别递归找到能使 (1) 确定状态的叶子即可。
    时间复杂度 (O(n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=200010,Inf=1e9;
    int n,tot,sum,ans,head[N],cnt[N],f[N][2];
    bool flag;
    
    struct edge
    {
    	int next,to;
    }e[N];
    
    void add(int from,int to)
    {
    	e[++tot].to=to;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    void dfs1(int x)
    {
    	if (head[x]==-1) f[x][0]=f[x][1]=1;
    		else f[x][0]=0,f[x][1]=Inf;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		dfs1(e[i].to);
    		f[x][0]+=f[e[i].to][1];
    		f[x][1]=min(f[x][1],f[e[i].to][0]);
    	}
    }
    
    void dfs2(int x,int k)
    {
    	if (head[x]==-1) cnt[x]++;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if (k && f[v][0]==f[x][1]) dfs2(v,0);
    		if (!k) dfs2(v,1);
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d",&n);
    	for (int i=2,x;i<=n;i++)
    	{
    		scanf("%d",&x);
    		add(x,i);
    	}
    	dfs1(1);
    	dfs2(1,0); dfs2(1,1);
    	for (int i=1;i<=n;i++)
    	{
    		if (cnt[i]==2) sum++,ans^=i;
    		if (cnt[i]==2 && !flag) printf("%d ",i),flag=1;
    	}
    	printf("%d %d",sum,ans);
    	return 0;
    }
    
  • 相关阅读:
    中译英26
    listen 59
    Speaking 1
    listen 58
    listen 57
    中译英25
    listen 56
    2018.2.27 RF module distance test part I
    中译英24
    第二章、PyQt5应用构建详细过程介绍
  • 原文地址:https://www.cnblogs.com/stoorz/p/13852944.html
Copyright © 2011-2022 走看看