FJ省队集训最终测试 T2

思路:发现如果一个人一共选了x个点,那么选中某一个点对的概率都是一样的,一个人选x个点的总方案是C(n,x),一个人选中某个点对的总方案是C(n-2,x-2),这样,那么选中某个点对的概率就是 x*(x-1)/(n*(n-1)),这样,我们就用树分治求出有多少对符合条件的对数,然后乘上每个人的概率即可。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define inf 0x7fffffff
 7 int son[200005],F[200005],root,vis[200005],pd[200005],c[200005];
 8 int n,go[200005],tot,first[200005],next[200005],dis[200005],num,sz,m,b[200005];
 9 int ans,cnt[200005];
10 double Ans;
11 int read(){
12     int t=0,f=1;char ch=getchar();
13     while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
14     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
15     return t*f;
16 }
17 void insert(int x,int y){
18     tot++;
19     go[tot]=y;
20     next[tot]=first[x];
21     first[x]=tot;
22 }
23 void add(int x,int y){
24     insert(x,y);insert(y,x);
25 }
26 void findroot(int x,int fa){
27     son[x]=1;F[x]=0;
28     for (int i=first[x];i;i=next[i]){
29         int pur=go[i];
30         if (vis[pur]||pur==fa) continue;
31         findroot(pur,x);
32         son[x]+=son[pur];
33         F[x]=std::max(F[x],son[pur]);
34     }
35     F[x]=std::max(F[x],num-son[x]);
36     if (F[x]<F[root]) root=x;
37 }
38 void bfs(int x){
39     int h=1,t=1;c[h]=x;pd[x]=sz;dis[x]=1;
40     while (h<=t){
41         int now=c[h++];
42         for (int i=first[now];i;i=next[i]){
43           int pur=go[i];
44           if (vis[pur]||pd[pur]) continue;
45           pd[pur]=sz;
46           dis[pur]=dis[now]+1;
47           c[++t]=pur;
48         }
49     }
50     for (int j=1;j<=m;j++)
51      for (int i=1;i<=t;i++)
52       if (b[j]>=dis[c[i]])
53       ans+=cnt[b[j]-dis[c[i]]];
54     for (int i=1;i<=t;i++)
55      cnt[dis[c[i]]]++;  
56 }
57 void solve(int x,int fa){
58     vis[x]=1;sz++;
59     memset(cnt,0,sizeof cnt);cnt[0]=1;
60     for (int i=first[x];i;i=next[i]){
61         int pur=go[i];
62         if (vis[pur]) continue;
63         bfs(pur);
64     }
65     int Sum=num;
66     for (int i=first[x];i;i=next[i]){
67         int pur=go[i];
68         if (vis[pur]) continue;
69         if (son[pur]>son[x]) num=Sum-son[x];
70         else num=son[pur];
71         root=0;
72         findroot(pur,0);
73         solve(root,x);
74     }
75 }
76 int main(){
77     n=read();m=read();
78     for (int i=1;i<=m;i++){
79         b[i]=read();
80     }
81     std::sort(b+1,b+1+m);
82     for (int i=1;i<n;i++){
83         int u=read(),v=read();
84         add(u,v);
85     }
86     F[0]=inf;root=0;num=n;
87     findroot(1,0);
88     solve(root,0);
89     double Ans=(((double)ans)/((double)n))/((double)n-1);
90     int m=n/3;
91     if (n%3) printf("%.2lf
",Ans*(m+1)*(m));
92     else printf("%.2lf
",Ans*(m-1)*m);
93     if (n%3==2) printf("%.2lf
",Ans*(m+1)*(m));
94     else printf("%.2lf
",Ans*(m-1)*m);
95     printf("%.2lf
",Ans*(m-1)*m);
96 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5656407.html