bzoj 2152:聪聪可可(点分治)

来源:互联网 发布:淘宝转盘抽奖怎么做 编辑:程序博客网 时间:2024/05/21 22:42

题面
题意:给你一棵树,有边权。随机选两个点,问它们路径长度为3的倍数的概率。

直接考虑点分治,还是找到重心x。用一遍dfs找出当前连通块内,到x距离模3为0,1,2的点分别有几个,然后统计答案。同一个连通块的点的路径不经过x,是不合法的,减去即可。

#include <iostream>#include <fstream>#include <algorithm>#include <cmath>#include <ctime>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define mmst(a, b) memset(a, b, sizeof(a))#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int N=40040,oo=1e9+7;void read(int &hy){    hy=0;    char cc=getchar();    while(cc<'0'||cc>'9')    cc=getchar();    while(cc>='0'&&cc<='9')    {        hy=(hy<<3)+(hy<<1)+cc-'0';        cc=getchar();    }}int n;int to[N],nex[N],val[N],head[N],cnt;int pre[N],siz[N],d[N],vis[N],root,sum;int dep[N],a[N];int ans,by[3];void add(int u,int v,int w){    to[++cnt]=v;    val[cnt]=w;    nex[cnt]=head[u];    head[u]=cnt;}void dfsRoot(int x,int fa){    pre[x]=fa;    siz[x]=1;    d[x]=0;    for(int h=head[x];h;h=nex[h])    if(!vis[to[h]]&&to[h]!=fa)    {        dfsRoot(to[h],x);        siz[x]+=siz[to[h]];        d[x]=max(d[x],siz[to[h]]);    }    d[x]=max(d[x],sum-siz[x]);    if(d[x]<d[root])    root=x;}void dfsDeep(int x,int fa){    a[++a[0]]=dep[x];    for(int h=head[x];h;h=nex[h])    if(!vis[to[h]]&&to[h]!=fa)    {        dep[to[h]]=(dep[x]+val[h])%3;        dfsDeep(to[h],x);    }}int cal(int x,int now){    dep[x]=now;    a[0]=0;    dfsDeep(x,0);    by[0]=by[1]=by[2]=0;    for(int i=1;i<=a[0];i++)    by[a[i]]++;    return by[0]*by[0]+by[1]*by[2]*2;}void dfsSol(int x){    siz[pre[x]]=sum-siz[x];    vis[x]=1;    ans+=cal(x,0);    for(int h=head[x];h;h=nex[h])    if(!vis[to[h]])    {        ans-=cal(to[h],val[h]);        sum=siz[to[h]];        root=0;        dfsRoot(to[h],0);        dfsSol(root);    }}int gcd(int x,int y){    if(!y)    return x;    return gcd(y,x%y);}int main(){    cin>>n;    ans=0;    for(int i=1;i<=n-1;i++)    {        int u,v,w;        read(u);        read(v);        read(w);        w=w%3;        add(u,v,w);        add(v,u,w);    }    sum=n;    root=0;    d[0]=oo;    dfsRoot(1,0);    dfsSol(root);    int gc=gcd(ans,n*n);    int fenmu=n*n/gc,fenzi=ans/gc;    cout<<fenzi<<"/"<<fenmu<<endl;}

这里写图片描述

原创粉丝点击