奶龙和噜噜的糖豆
题意
现在有一颗以 为根的树,奶龙先选择一个叶子作为 ,噜噜再选择一个叶子作为 ,噜噜从 1 出发,先走到 点的话,奶龙赢,否则奶龙输,奶龙想要自己赢,噜噜不想要奶龙赢,双方都采取最优策略,计算奶龙赢得概率
题解
如果糖豆走到既没有 ,也没有 的节点,那么糖豆一定会在某个节点处往回走,所以只需要计算在既可以走到 ,又可以走到 的时候,这一条路径上的概率,假设我现在在 点,距离 点为 ,距离 点为 ,所以此时奶龙获胜的概率为:
此时糖豆的出发点在 1, 假设接下来糖豆会走到 路径的某点 上
那么:
其中的 是已知的,所以我们只需要求出
可得:
所以只需要枚举 两个点,计算就可以求出答案,同时需要维护当前最小的答案的分数用于比较
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define vi vector<int>
#define vii vector<vi>
#define viii vector<vii>
#define pii pair<int,int>
//#define lc p<<1
//#define rc (p<<1) + 1
const int N = 2e5 + 10;
const int M = 5e5 + 10;
const int INF = 1e18;
int mod = 998244353;
int qpow(int a, int b){
int res = 1;
while(b){
if(b & 1) res = (res * a) % mod;
a = a * a % mod;
b >>= 1;
}
return res % mod;
}
int mn(int x){
return qpow(x, mod - 2);
}
vi G[5201];
//需要 1 到 a 的距离,1 到 b 的距离,a 到 b 的距离,a,b就是两个lcm相加就好了
vii dis(5201, vi(5201));
void dfs(int u, int v, int fa){ //我已知 dis[u][v], v 是 fa 的儿子,其实就是找从 u 出发到每个点的最短距离
for(auto k : G[v]){
if(k == fa) continue;
dis[u][k] = dis[u][v] + 1;
dfs(u, k, v);
}
return;
}
void solve(){
int n; cin >> n;
vi cnt(n + 1);
rep(i, 1, n - 1){
int x, y; cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
cnt[x] ++;
cnt[y] ++;
}
rep(i, 1, n){
//没个节点从它的儿子开始搜
for(auto v : G[i]){
dis[i][v] = 1;
dfs(i, v, i);
}
}
int fzz = 0, fmm = 0; //记录最大的概率的分子分母
rep(i, 2, n){
if(cnt[i] > 1) continue;
int fz = 0, fm = 0;
rep(j, 2, n){
if(i == j) continue;
if(cnt[j] > 1) continue;
int t_fz = dis[i][j] + dis[1][j] - dis[1][i];
int t_fm = 2 * dis[i][j];
//cout << t_fz << " " << t_fm << endl;
if(fz == 0 && fm == 0 && t_fz != t_fm){
fz = t_fz; fm = t_fm;
}else if(t_fz * fm < t_fm * fz && t_fz != t_fm){
fz = t_fz;
fm = t_fm;
}
}
if(fzz == 0 && fmm == 0 && fz != fm){
fzz = fz; fmm = fm;
}else if(fz * fmm > fm * fzz && fz != fm){
fzz = fz;
fmm = fm;
}
}
//cout << fz << " " << fm << endl;
cout << fzz * mn(fmm) % mod << endl;
rep(i, 1, n){
G[i].clear();
rep(j, 1, n){
dis[i][j] = 0;
}
}
return;
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T = 1;
cin>>T;
while(T--) solve();
return 0;
}