首页 技术 正文
技术 2022年11月8日
0 收藏 635 点赞 1,129 浏览 2282 个字

【BZOJ4675】点对游戏

Description

桑尼、露娜和斯塔在玩点对游戏,这个游戏在一棵节点数为n的树上进行。桑尼、露娜和斯塔三人轮流从树上所有未被占有的节点中选取一点,归为己有,轮流顺序为桑尼、露娜、斯塔、桑尼、露娜……。该选取过程直到树上所有点都被选取后结束。选完点后便可计算每人的得分。点对游戏中有m个幸运数,在某人占据的节点中,每有一对点的距离为某个幸运数,就得到一分。(树上两点之间的距离定义为两点之间的简单路径的边数)你的任务是,假设桑尼、露娜和斯塔每次选取时,都是从未被占有的节点中等概率选取一点,计算每人的期望得分。

Input

第一行两个整数n、m,分别表示树的节点数和幸运数的数目。第二行m个互异正整数,表示m个幸运数。以下n-1行,每行两个整数u、v,表示节点u和节点v之间有边。节点从1到n编号。3 <= n <= 50000, m <= 10,幸运数大小 <= n

Output

三行实数,分别表示桑尼、露娜和斯塔的期望得分,保留两位小数。

Sample Input

5 2
1 3
1 2
1 5
2 3
2 4

Sample Output

0.60
0.60
0.00

题解:本题的做法比较神。

先用点分治统计出所有幸运点对的个数,然后分别统计每个人都选出了多少个点对,用选出的点对数*幸运点对数/总点对数 即是答案。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=50010;
int sum;
int n,m,cnt,rt,mn,tot;
int to[maxn<<1],next[maxn<<1],head[maxn],dep[maxn],vis[maxn],siz[maxn],luck[20],f[maxn],g[maxn],md[maxn];
double ans[maxn],s[maxn];
void getrt(int x,int fa)
{
siz[x]=1;
int tmp=0;
for(int i=head[x];i!=-1;i=next[i])if(to[i]!=fa&&!vis[to[i]])
getrt(to[i],x),siz[x]+=siz[to[i]],tmp=max(tmp,siz[to[i]]);
tmp=max(tmp,tot-siz[x]);
if(tmp<mn)mn=tmp,rt=x;
}
void getmd(int x,int fa,int dep)
{
siz[x]=1,md[x]=0;
for(int i=head[x];i!=-1;i=next[i])if(to[i]!=fa&&!vis[to[i]])
getmd(to[i],x,dep+1),siz[x]+=siz[to[i]],md[x]=max(md[x],md[to[i]]+1);
}
void getdep(int x,int fa,int dep)
{
g[dep]++;
for(int i=1;i<=m;i++)if(dep<=luck[i])sum+=f[luck[i]-dep];
for(int i=head[x];i!=-1;i=next[i])if(to[i]!=fa&&!vis[to[i]])getdep(to[i],x,dep+1);
}
void dfs(int x)
{
vis[x]=1;
getmd(x,0,0);
f[0]=1;
for(int i=head[x];i!=-1;i=next[i])if(!vis[to[i]])
{
getdep(to[i],x,1);
for(int j=0;j<=md[to[i]]+1;j++)f[j]+=g[j],g[j]=0;
}
memset(f,0,sizeof(f[0])*(md[x]+2));
for(int i=head[x];i!=-1;i=next[i])if(!vis[to[i]])tot=siz[to[i]],mn=1<<30,getrt(to[i],x),dfs(rt);
}
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
inline int rd()
{
int ret=0,f=1;char gc=getchar();
while(gc<'0'||gc>'9'){if(gc=='-')f=-f;gc=getchar();}
while(gc>='0'&&gc<='9')ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
//freopen("game0.in","r",stdin);
//freopen("game.out","w",stdout);
n=rd(),m=rd();
int i,a,b;
for(i=1;i<=m;i++)luck[i]=rd();
memset(head,-1,sizeof(head));
for(i=1;i<n;i++)a=rd(),b=rd(),add(a,b),add(b,a);
tot=n,mn=1<<30,getrt(1,0),dfs(rt);
a=(n+2)/3,printf("%.2lf\n",1.0*a*(a-1)*sum/(1.0*n*(n-1)));
a=(n+1)/3,printf("%.2lf\n",1.0*a*(a-1)*sum/(1.0*n*(n-1)));
a=n/3,printf("%.2lf\n",1.0*a*(a-1)*sum/(1.0*n*(n-1)));
return 0;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,492
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,495
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,133
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,297