[ABC314F] A Certain Game 题解
考虑合并队伍的性质,显然一路合并上去这个结构是个树。用启发式合并的思想,每次先把
最后对于每个点跳父亲查找、累加贡献即可。记得每次合并两个集合的时候大集合要减去小集合的贡献,因为跳父亲的时候会被算一次而它本来不该被算进去。
实现借助了 AtCoder Library 的并查集和 modint。
放代码:
#include<bits/stdc++.h>
#include<atcoder/all>
using namespace std;
using mint=atcoder::modint998244353;
int main(){
ios::sync_with_stdio(false);
int n; cin>>n;
vector<int> p(n,-1);
vector<mint> c(n);
atcoder::dsu d(n);
for(int i=1;i<n;i++){
int u,v; cin>>u>>v; u--,v--;
u=d.leader(u),v=d.leader(v);
int a=d.size(u),b=d.size(v);
if(u!=d.merge(u,v))swap(u,v),swap(a,b);
c[u]+=mint(a)/(a+b),c[v]+=mint(b)/(a+b)-c[u],p[v]=u;
} // 连边过程
vector<bool> b(n);
function<void(int)> dfs=[&](int u){
if(!b[u])if(b[u]=true;~p[u])dfs(p[u]),c[u]+=c[p[u]];
}; // 继承父亲
for(int i=0;i<n;i++)
dfs(i),cout<<c[i].val()<<' ';
return 0;
}