NC204126. 牛牛的树行棋
描述
输入描述
第一行输入一个,表示树含有n个点。
接下来n-1行,每行输入一个x,y,()表示x与y相连。
输出描述
对于每组数据,如果牛牛(先手)能赢则输出‘YES’,否则输出‘NO’。
如果能赢,请在第二行跟着输出一个正整数ans,表示第一步的必胜策略数目。
示例1
输入:
3 1 2 1 3
输出:
YES 2
说明:
示例2
输入:
4 1 2 2 3 3 4
输出:
NO
说明:
C++11(clang++ 3.9) 解法, 执行用时: 851ms, 内存消耗: 62316K, 提交时间: 2020-05-12 11:48:47
#include<bits/stdc++.h> using namespace std; const int N=1e6+100; vector<int>G[N]; int cnt[N],sg[N]; int tmp=0,ans=0; void dfs1(int x,int fa) { for(int v:G[x]) { if(v==fa) continue; dfs1(v,x); sg[x]=max(sg[x],sg[v]+1); } tmp^=sg[x]; } void dfs2(int x,int fa) { ans-=cnt[tmp^sg[x]]; cnt[sg[x]]++; for(int v:G[x]) { if(v==fa)continue; dfs2(v,x); } ans+=cnt[tmp^sg[x]]; } int main() { int n; cin>>n; for(int i=1;i<n;i++) { int x,y; cin>>x>>y; G[x].push_back(y); G[y].push_back(x); } dfs1(1,0); if(tmp==0) puts("NO"); else { puts("YES"); dfs2(1,0); cout<<ans<<endl; } return 0; }
C++14(g++5.4) 解法, 执行用时: 718ms, 内存消耗: 53988K, 提交时间: 2020-05-11 01:02:46
#include<bits/stdc++.h> using namespace std; const int N=5e5+10; vector<int> e[N]; int sg[N<<1],n,cnt[N<<1],u,v,sum,xorsum; void dfs1(int x,int pre){ for(auto i:e[x]) if(i!=pre) { dfs1(i,x); sg[x]=max(sg[x],sg[i]+1); } xorsum^=sg[x]; } void dfs2(int x,int pre){ cnt[sg[x]]++; sum+=cnt[sg[x]^xorsum]; for(auto i:e[x]) if(i!=pre) dfs2(i,x); cnt[sg[x]]--; } int main(){ cin>>n; for(int i=1;i<n;i++){ cin>>u>>v; e[u].push_back(v), e[v].push_back(u); } dfs1(1,-1); if(xorsum){ dfs2(1,-1); cout<<"YES"<<endl<<sum<<endl; }else cout<<"NO"<<endl; return 0; }