码迷,mamicode.com
首页 > 其他好文 > 详细

[bzoj2152]聪聪可可(点分治)

时间:2017-09-09 00:42:59      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:bsp   efi   init   复杂   typedef   math   scan   name   getchar   

题意:在一棵树中,求两点之间距离是3的倍数的概率。

解题关键:$p = \frac{{\sum {nu{m_0}*nu{m_0} + nu{m_1}*nu{m_2}*2} }}{{n*n}}$

求概率分子分母必须对应,分母是无序的,则分子也必须是无序的。

复杂度:$O(n\log n)$

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<cmath>
  7 #define inf 0x3f3f3f3f
  8 #define maxn 20004
  9 using namespace std;
 10 typedef long long ll;
 11 int head[maxn],cnt,n,k=3,ans,size,s[maxn],f[maxn],root,depth[maxn],num;//vis代表整体的访问情况,每个dfs不应该只用vis来存储
 12 bool vis[maxn];
 13 ll ans1,ans2,ans3;
 14 struct edge{
 15     int to,w,nxt;
 16 }e[maxn<<1];
 17 void add_edge(int u,int v,int w){
 18     e[cnt].to=v;
 19     e[cnt].w=w;
 20     e[cnt].nxt=head[u];
 21     head[u]=cnt++;
 22 }
 23 
 24 inline int read(){
 25     char k=0;char ls;ls=getchar();for(;ls<0||ls>9;k=ls,ls=getchar());
 26     int x=0;for(;ls>=0&&ls<=9;ls=getchar())x=(x<<3)+(x<<1)+ls-0;
 27     if(k==-)x=0-x;return x;
 28 }
 29 
 30 void get_root(int u,int fa){//get_root会用到size
 31     s[u]=1;f[u]=0;//f是dp数组
 32     for(int i=head[u];i!=-1;i=e[i].nxt){
 33         int v=e[i].to;
 34         if(v==fa||vis[v]) continue;
 35         get_root(v,u);
 36         s[u]+=s[v];
 37         f[u]=max(f[u],s[v]);
 38     }
 39     f[u]=max(f[u],size-s[u]);
 40     root=f[root]>f[u]?u:root;
 41 }
 42 
 43 void get_depth_size(int u,int fa,int dis){//同时获取size和depth
 44     if(dis%3==0) ans1++;
 45     else if(dis%3==1) ans2++;
 46     else ans3++;
 47     s[u]=1;
 48     for(int i=head[u];i!=-1;i=e[i].nxt){
 49         int v=e[i].to;
 50         if(v==fa||vis[v]) continue;
 51         get_depth_size(v,u,dis+e[i].w);
 52         s[u]+=s[v];
 53     }
 54 }
 55 
 56 int calc(int u,int fa,int w){
 57     ans1=ans2=ans3=0;
 58     get_depth_size(u,fa,w);
 59     return ans1*ans1+ans2*ans3*2;
 60 }
 61 
 62 void work(int u){
 63     vis[u]=true;
 64     ans+=calc(u,-1,0);
 65     for(int i=head[u];i!=-1;i=e[i].nxt){
 66         int v=e[i].to;
 67         if(vis[v]) continue;
 68         ans-=calc(v,u,e[i].w);
 69         size=s[v],root=0;
 70         get_root(v,u);
 71         work(root);
 72     }
 73 }
 74 
 75 void init(){
 76     memset(vis,false, sizeof vis);
 77     memset(head,-1,sizeof head);
 78     ans=cnt=0;
 79 }
 80 
 81 
 82 int main(){
 83     int a,b,c;
 84     f[0]=inf;
 85     while(scanf("%d",&n)!=EOF){
 86         init();
 87         for(int i=0;i<n-1;i++){
 88             a=read(),b=read(),c=read();
 89             add_edge(a,b,c);
 90             add_edge(b,a,c);
 91         }
 92         size=n,root=0;
 93         get_root(1,-1);
 94         work(root);
 95         int gg=__gcd(ans,n*n); 
 96         printf("%d/%d\n",ans/gg,n*n/gg);
 97     }
 98     return 0;
 99     
100 }

 

[bzoj2152]聪聪可可(点分治)

标签:bsp   efi   init   复杂   typedef   math   scan   name   getchar   

原文地址:http://www.cnblogs.com/elpsycongroo/p/7496873.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!