题目链接:Problem - 7450 (hdu.edu.cn)
思路:每个点的获胜概率为p/15,根据期望公式可求得每个点的期望为E(x)=;由于跑最短路比较难记录每条路跑了多少个点所以我们可以预处理每一个点的分母将所有分母通分为1~15的最小公倍数即可直接跑dijkstra来求出最大的期望;
ac代码如下:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf=0x3f3f3f3f;
const int N=1e5+5;
const int mingcd=360360;//1~15的最小公倍数
#define pii pair<int,int>
int n,m,cnt;
vector<pii> ve;
map<int,int> mp;
struct Edge{
int to;
int w;
int next;
}edge[N*4];
int s[N];
int ans[N];
int head[N*4];
int vis[N];
void init(){
cnt=0;
ve.clear();
for(int i=1;i<=n;i++){
ans[i]=0;
vis[i]=0;
head[i]=-1;
s[i]=0;
}
}
void add_edge(int u,int v,int w){
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
struct cmp{
bool operator()(pii a,pii b){
return a.second<b.second;//需要边的权值更大
}
};
void dijkstra(){
ans[1]=s[1];//第一个房必须打
priority_queue<pii,vector<pii>,cmp> q;
q.push({1,ans[1]});
while(!q.empty()){
int x=q.top().first;
q.pop();
vis[x]=1;
for(int i=head[x];i!=-1;i=edge[i].next){
if(!vis[edge[i].to]&&ans[edge[i].to]<ans[x]+edge[i].w){//路程越长期望越大
ans[edge[i].to]=ans[x]+edge[i].w;
q.push({edge[i].to,ans[edge[i].to]});
}
}
}
}
signed main(){
for(int i=1;i<=15;i++){
mp[i]=(i,15*mingcd/i);
}
int t;
cin>>t;
while(t--){
cin>>n;
init();
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
ve.push_back({a,b});
}
for(int i=1;i<=n;i++){
int a;
cin>>a;
s[i]=mp[a];
}
for(int i=0;i<ve.size();i++){
add_edge(ve[i].first,ve[i].second,s[ve[i].second]);
add_edge(ve[i].second,ve[i].first,s[ve[i].first]);
}
dijkstra();
int amx=0;
for(int i=1;i<=n;i++){
amx=max(amx,ans[i]);
}
int g_cd=__gcd(amx,mingcd);
cout<<amx/g_cd<<'/'<<mingcd/g_cd<<endl;
}
return 0;
}