P4096-[HEOI2013]Eden的博弈树

it2024-12-12  14

正题

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


题目大意

一个博弈树,黑方先手。定义一个最小的叶子节点集为黑胜状态为黑方胜利集合,白色亦然。求所有既属于黑方胜利集合有属于白方胜利集合的点。


解题思路

f i , 0 / 1 f_{i,0/1} fi,0/1表示 i i i子树中的最小黑发/白方胜利集和,然后可以根据这个求出所有的胜利集合点。

时间复杂度 O ( n ) O(n) O(n)


c o d e code code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e5+10; struct node{ int to,next; }a[N]; int n,tot,ls[N],f[N][2]; bool con[N][2]; void addl(int x,int y){ a[++tot].to=y; a[tot].next=ls[x]; ls[x]=tot;return; } void dfs(int x,int j,int k){ if(!ls[x]){f[x][k]=1;return;} if(j!=k)f[x][k]=2147483647; for(int i=ls[x];i;i=a[i].next){ int y=a[i].to; dfs(y,j^1,k); if(j!=k)f[x][k]=min(f[x][k],f[y][k]); else f[x][k]+=f[y][k]; } return; } void solve(int x,int j,int k){ if(!ls[x])con[x][k]=1; for(int i=ls[x];i;i=a[i].next){ int y=a[i].to; if(j!=k&&f[y][k]!=f[x][k])continue; solve(y,j^1,k); } return; } int main() { scanf("%d",&n); for(int i=2;i<=n;i++){ int x;scanf("%d",&x); addl(x,i); } dfs(1,0,0);dfs(1,0,1); solve(1,0,0);solve(1,0,1); int ans1=2147483647,ans2=0,ans3=0; for(int i=1;i<=n;i++) if(con[i][1]&&con[i][0]) ans1=(ans1<2147483647)?ans1:i,ans2++,ans3^=i; printf("%d %d %d\n",ans1,ans2,ans3); }
最新回复(0)