FJ省队集训最终测试 T2



思路:发现如果一个人一共选了x个点,那么选中某一个点对的概率都是一样的,一个人选x个点的总方案是C(n,x),一个人选中某个点对的总方案是C(n-2,x-2),这样,那么选中某个点对的概率就是 x*(x-1)/(n*(n-1)),这样,我们就用树分治求出有多少对符合条件的对数,然后乘上每个人的概率即可。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define inf 0x7fffffff
int son[],F[],root,vis[],pd[],c[];
int n,go[],tot,first[],next[],dis[],num,sz,m,b[];
int ans,cnt[];
double Ans;
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-')f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);insert(y,x);
}
void findroot(int x,int fa){
son[x]=;F[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]||pur==fa) continue;
findroot(pur,x);
son[x]+=son[pur];
F[x]=std::max(F[x],son[pur]);
}
F[x]=std::max(F[x],num-son[x]);
if (F[x]<F[root]) root=x;
}
void bfs(int x){
int h=,t=;c[h]=x;pd[x]=sz;dis[x]=;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (vis[pur]||pd[pur]) continue;
pd[pur]=sz;
dis[pur]=dis[now]+;
c[++t]=pur;
}
}
for (int j=;j<=m;j++)
for (int i=;i<=t;i++)
if (b[j]>=dis[c[i]])
ans+=cnt[b[j]-dis[c[i]]];
for (int i=;i<=t;i++)
cnt[dis[c[i]]]++;
}
void solve(int x,int fa){
vis[x]=;sz++;
memset(cnt,,sizeof cnt);cnt[]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
bfs(pur);
}
int Sum=num;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
if (son[pur]>son[x]) num=Sum-son[x];
else num=son[pur];
root=;
findroot(pur,);
solve(root,x);
}
}
int main(){
n=read();m=read();
for (int i=;i<=m;i++){
b[i]=read();
}
std::sort(b+,b++m);
for (int i=;i<n;i++){
int u=read(),v=read();
add(u,v);
}
F[]=inf;root=;num=n;
findroot(,);
solve(root,);
double Ans=(((double)ans)/((double)n))/((double)n-);
int m=n/;
if (n%) printf("%.2lf\n",Ans*(m+)*(m));
else printf("%.2lf\n",Ans*(m-)*m);
if (n%==) printf("%.2lf\n",Ans*(m+)*(m));
else printf("%.2lf\n",Ans*(m-)*m);
printf("%.2lf\n",Ans*(m-)*m);
}
FJ省队集训最终测试 T2的更多相关文章
- FJ省队集训最终测试 T3
思路:状态压缩dp,f[i][j[[k]代表i行j列这个格子,连续的状态为k,这个连续的状态是什么?就是下图 X格子代表我当前走到的地方,而这里的状态就是红色部分,也就是连续的一段n的状态,我们是分每 ...
- FJ省队集训DAY4 T2
XXX #include<cstdio> #include<iostream> #include<cmath> #include<cstring> #i ...
- FJ省队集训DAY3 T2
思路:如果一个DAG要的路径上只要一条边去切掉,那么要怎么求?很容易就想到最小割,但是如果直接做最小割会走出重复的部分,那我们就这样:反向边设为inf,这样最小割的时候就不会割到了,判断无解我们直接用 ...
- FJ省队集训DAY2 T2
思路:我们可以考虑三角剖分,这样问题就变成考虑三角形的选取概率和三角形内有多少个点了. 先用树状数组预处理出三角剖分的三角形中有多少个点,然后用线段树维护,先用原点极角排序,然后枚举i,再以i极角排序 ...
- FJ省队集训DAY3 T1
思路:我们考虑如果取掉一个部分,那么能影响到最优解的只有离它最近的那两个部分. 因此我们考虑堆维护最小的部分,离散化离散掉区间,然后用线段树维护区间有没有雪,最后用平衡树在线段的左右端点上面维护最小的 ...
- FJ省队集训DAY2 T1
思路:转换成n条三维空间的直线,求最大的集合使得两两有交点. 有两种情况:第一种是以某2条直线为平面,这时候只要统计这个平面上有几条斜率不同的直线就可以了 还有一种是全部交于同一点,这个也只要判断就可 ...
- FJ省队集训DAY1 T1
题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆. 思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会 ...
- FJ省队集训DAY4 T3
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #inclu ...
- FJ省队集训DAY5 T1
思路:考试的时候打了LCT,自以为能过,没想到只能过80.. 考完一想:lct的做法点数是100W,就算是nlogn也会T. 讲一下lct的做法把:首先如果一条边连接的两个点都在同一个联通块内,那么这 ...
随机推荐
- 【网贷投资手册】P2P行业揭秘
[网贷投资手册]P2P行业揭秘 (中国电子商务研究中心讯)如果你手头有100元,你会拿它来做什么?跟好朋友去吃一顿?跟女朋友去看场电影?还是……你会想到拿100元去投资吗?100元太少了,买一 ...
- HDOJ(HDU) 1562 Guess the number(水题,枚举就行)
Problem Description Happy new year to everybody! Now, I want you to guess a minimum number x betwwn ...
- samba服务器的搭建及使用
一.Samba服务器的安装及配置 1.samba服务器的安装 rpm –ivh /mnt/Packages/samba-3. 5. 10-125. el6.i686.rpm 需要挂载红帽6的光盘 2. ...
- CDH-5.4.3离线安装
使用CM离线安装CDH-5.4.3,如下: cdh5.4.3安装 配置/etc/hosts vim /etc/hosts 192.168.10.1 s1 192.168.10.2 s2 192.168 ...
- char和int的转换
import java.util.Scanner; public class test7 { public static void main(String[] args) { // TODO Auto ...
- MYSQL常用操作函数的封装
1.mysql常用函数封装文件:mysql.func.php <?php /** * 连接MYSQL函数 * @param string $host * @param string $usern ...
- 【ArcGIS 10.2新特性】地理数据(Geodatabase 和database)10.2 新特性
1. 大数据支持 ArcGIS与Hadoop集成,将提供一个开源的工具包用于大数据的空间分析,开发者将通过该工具包构建定制化的工作流并在ArcGIS当中执行. 支持更多的大数据平台数据 ...
- 常见算法:C语言求最小公倍数和最大公约数三种算法
最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们的公倍数,当中一个最小的公倍数是他们的最小公倍数,相同地,若干个整数公有的倍数中最小的正整数称为它们的最小公倍数,维基百科:定义点击打开链接 求 ...
- leetcodequestion_56 Merge Intervals
Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6],[8, ...
- Android 推断当前Activity是不是最后一个Activity 以及 应用或Activity是否存在
推断当前Activity是最后一个Activity: 在Activity的方法中, 有一个方法isTaskRoot()方法, 这种方法能够推断当前Activity是否是最后一个Activity, 假 ...