【BZOJ】聪聪可可-点分治

原创 2018年04月15日 19:51:33

传送门:bzoj2152


题意

在纸上画n个“点”,并用n-1条“边”把这n个“点”恰好连通(其实这就是一棵树)。并且每条“边”上都有一个数。接下来由聪聪和可可分别随即选一个点,如果两个点之间所有边上数的和加起来恰好是3的倍数,则判聪聪赢,否则可可赢。求对于这张图聪聪的获胜概率是多少。


数据范围

对于100%的数据,n<=20000。


题解

点分治板题,模一下就好了。


代码

#include<bits/stdc++.h>
const int INF=0x7fffffff;
using namespace std;
typedef long long ll;
const int N=2e4+10;
ll qw,sum[4],sim[N],mx[N],ans,S;
int n,x,y,mod=3,tot;
int head[N],to[N<<1],nxt[N<<1],w[N<<1];
int root,MX;
bool vis[N];

inline void lk(int u,int v,int val){
    to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=val;
}

inline void getroot(int now,int f)
{
    sim[now]=1;mx[now]=0;
    for(int i=head[now];i;i=nxt[i]){
        int e=to[i];
        if(vis[e]||(e==f)) continue;
        getroot(e,now);
        sim[now]+=sim[e];
        mx[now]=max(mx[now],sim[e]);
    }
    mx[now]=max(mx[now],S-sim[now]);
    if(mx[now]<MX){root=now;MX=mx[now];}
}

inline void query(int now,int f,int val)
{
    sum[val]++;
    for(int i=head[now];i;i=nxt[i])
    {
        int e=to[i];
        if(vis[e]||(e==f)) continue;
        query(e,now,(val+w[i])%mod);
    }
}

inline ll solve(int now,int val)
{
    sum[0]=sum[1]=sum[2]=0;
    query(now,0,val);
    return (sum[0]*sum[0]+2*sum[1]*sum[2]);
}

inline void divide(int now)
{
    ans+=solve(now,0);
    vis[now]=true;
    for(int i=head[now];i;i=nxt[i]){
        int e=to[i];
        if(vis[e]) continue;
        ans-=solve(e,w[i]);
        MX=INF;root=0;S=sim[e];
        getroot(e,0);
        divide(root);
    }
}

inline ll gcd(ll a,ll b)
{
    return (b==0)? a:gcd(b,a%b);
}

int main(){
    memset(vis,false,sizeof(vis));
    scanf("%d",&n);
    for(int c,i=1;i<n;i++){
       scanf("%d%d%d",&x,&y,&c);
       c%=mod;  
       lk(x,y,c);lk(y,x,c);
    }
    S=n;MX=INF;
    getroot(1,0);
    divide(root);
    qw=n*n;ll k=gcd(ans,qw);
    printf("%lld/%lld\n",ans/k,qw/k);
    return 0;
}

版权声明:侵删,转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/79952347

SpringBoot + Redis + MQ 高并发点赞项目实战

-
  • 1970年01月01日 08:00

【BZOJ】2152 聪聪可可 点分治

题目传送门 这道题的正解——点分治还是挺好想到的,因为题目已经明确给出这道题是以树为基础的。 这题的统计答案与点分治的模板有些不同,不过也还是挺好想到的。 题目要求任意两点的距离是3的倍数的点对...
  • lyfsb
  • lyfsb
  • 2017-05-30 20:11:42
  • 180

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

The secret oppotunities are hidden inside every failure.
  • Clove_unique
  • Clove_unique
  • 2016-09-20 14:21:20
  • 532

bzoj2152: 聪聪可可(点分治)

2152: 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MB Submit: 2209  Solved: 1166 [Submit][Status][Discu...
  • qq_34564984
  • qq_34564984
  • 2016-12-19 22:41:31
  • 206

BZOJ 1415 NOI2005 聪聪和可可 期望DP+记忆化搜索 BZOJ200题达成&&NOI2005全AC达成

题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇 今天早上起床...
  • PoPoQQQ
  • PoPoQQQ
  • 2014-11-07 17:50:01
  • 2378

bzoj2152 聪聪可可【点分治】

题意:中文题。。。。。。 按点分治的的方法,每次都求出经过根的可行方案的个数,这里要求是3的倍数,所以我们可以把距离根的距离%3,那么取余后的距离根的距离为1和2的可以组成3,两个0当然也可以,这里...
  • eeeaaaaa
  • eeeaaaaa
  • 2015-05-08 19:33:55
  • 317

洛谷 P3806 【模板】点分治1

#include #include #include #define K 10000005 #define N 10005 using std::max; int n,m; int hd[N],nxt...
  • ureaster
  • ureaster
  • 2018-01-06 13:06:48
  • 93

BZOJ 2152 聪聪可可 树的点分治/树形DP

题目大意:给定一棵树,每条边上有边权,求距离为3的倍数的有序点对 树的点分治,对于每个重心统计出每棵子树距离重心长度为0/1/2的点的数量,计算出ans即可 最后ans*2+1 和n^2进行一下约...
  • PoPoQQQ
  • PoPoQQQ
  • 2014-10-27 10:11:50
  • 2772

【点分治】的学习笔记和众多例题

包含点分治多道例题: 【POJ 1741 & BZOJ 1468 & BZOJ 3365】 【BZOJ 2152】 【BZOJ 2599】 【BZOJ 1316】 很详细的一篇文章,20分钟教会你点分...
  • nixinyis
  • nixinyis
  • 2017-03-23 16:45:45
  • 2186

BZOJ2152 聪聪可可(点分治)

【题解】 基础的点分治题 还是分为路径是否经过root来讨论,计算点到根的距离时,一边计算,一边统计距离对3取模等于0,1,2的点的个数  注意:统计答案时(a,a)算1次,(a,b)算...
  • cjk_cjk
  • cjk_cjk
  • 2015-02-18 01:23:58
  • 444
收藏助手
不良信息举报
您举报文章:【BZOJ】聪聪可可-点分治
举报原因:
原因补充:

(最多只允许输入30个字)