首页 > 代码库 > ARC078 D.Fennec VS. Snuke(树上博弈)
ARC078 D.Fennec VS. Snuke(树上博弈)
题目大意:
给定一棵n个结点的树
一开始黑方占据1号结点,白方占据n号结点
其他结点都没有颜色
每次黑方可以选择黑色结点临近的未染色结点,染成黑色
白方同理。
最后谁不能走谁输。
题解:
其实简单想想就可以想明白。
黑方肯定要往通往白方的最短路延伸,白方也是这样。
因为这样每次你可以最大化可行动次数。
所以先以1为根,dfs一遍,然后找到路径。
模拟一下走路径的过程,路径走光了就比谁的可行动次数多(有点像围棋的气的感觉),输出结果就可以了
#include <iostream> #include <cstdio> #include <deque> #include <vector> #include <vector> using namespace std; const int maxn = 1e5 + 100; vector<int> G[maxn]; int deep[maxn], sz[maxn], f[maxn]; deque<int> Q; void dfs(int x, int fa, int d){ deep[x] = d; sz[x] = 1; f[x] = fa; for(auto to : G[x]){ if(to == fa) continue; dfs(to, x, d+1); sz[x] += sz[to]; } } int main() { int n, x, y; cin>>n; for(int i = 1; i < n; i++){ scanf("%d %d", &x, &y); G[x].push_back(y); G[y].push_back(x); } dfs(1, 1, 1); x = n; while(x != 1){ Q.push_back(x); x = f[x]; } Q.push_back(1); int ansB = 0, ansW = 0, B = 0, W, temp; while(1){ if(Q.empty()){ ansB += sz[B]-1-sz[W]; ansW = sz[W] - ansW; if(ansB <= ansW) cout<<"Snuke"<<endl; else cout<<"Fennec"<<endl; return 0; } temp = B; B = Q.back(); Q.pop_back(); if(temp != 0) ansB += sz[temp]-sz[B]-1; if(Q.empty()) { ansB += sz[B]-1-sz[W]; ansW = sz[W] - ansW; if(ansW <= ansB) cout<<"Fennec"<<endl; else cout<<"Snuke"<<endl; return 0; } W = Q.front(); Q.pop_front(); ansW++; } }
ARC078 D.Fennec VS. Snuke(树上博弈)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。