google提交网站,wordpress 采集,六安城市网地址,高级设计师培训班正题
题目链接:https://www.luogu.com.cn/problem/AT2667 题目大意
给出nnn个点的一棵树#xff0c;每次可以割掉一条和根节点联通的边#xff0c;轮流操作直到不能操作的输#xff0c;求是否先手必胜。 1≤n≤21051\leq n\leq 2\times 10^51≤n≤2105 解题思路
挺巧妙的…正题
题目链接:https://www.luogu.com.cn/problem/AT2667 题目大意
给出nnn个点的一棵树每次可以割掉一条和根节点联通的边轮流操作直到不能操作的输求是否先手必胜。
1≤n≤2×1051\leq n\leq 2\times 10^51≤n≤2×105 解题思路
挺巧妙的一个东西考虑通过每个子树的SGSGSG来求根的SGSGSG。
考虑一个等价的问题就是假设我们有kkk个子树那么我们可以把根节点复制kkk份然后每个单独连接。
然后考虑我们知道了一棵树的SGSGSG然后往上加一个节点时新的SGSGSG是多少。
用DAGDAGDAG来考虑的话不难发现我们其实是多了一个节点并且连向所有的状态所以新的SGSGSG值加一就好连。
所以每个点子树的SGSGSG就等于他儿子节点子树的SG1SG1SG1的异或和
时间复杂度O(n)O(n)O(n) code
#includecstdio
#includecstring
#includealgorithm
using namespace std;
const int N2e510;
struct node{int to,next;
}a[N1];
int n,tot,ls[N],sg[N];
void addl(int x,int y){a[tot].toy;a[tot].nextls[x];ls[x]tot;return;
}
void dfs(int x,int fa){for(int ils[x];i;ia[i].next){int ya[i].to;if(yfa)continue;dfs(y,x);sg[x]^sg[y]1;}return;
}
int main()
{scanf(%d,n);for(int i1;in;i){int x,y;scanf(%d%d,x,y);addl(x,y);addl(y,x);}dfs(1,1);if(sg[1])puts(Alice);else puts(Bob);return 0;
}