zoukankan      html  css  js  c++  java
  • luoguP2634聪聪可可(点分治)

    题目链接:https://www.luogu.org/problem/P2634

    题意:给一颗树,求距离的模3为0的点对数量,注意(1,1)算一个点对,(1,2)和(2,1)算两个点对。

    思路:和点分治模板题很像,那个是求距离为k的点对数,这题更简单一点,求距离模3为0的点对数。还是一般的套路,求重心,计算点到重心的距离模3的值dis[i],然后用num[i]统计dis=i的点数,然后加上所有组合,即(num[0]-1)*num[0]/2+num[1]*num[2],然后减去在同一个子树中的不合法组合。最后因为我们求的是不同点对数,需要乘2,再加上n(自己和自己组成的点对)。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int maxn=20005;
    const int inf=0x3f3f3f3f;
    struct node1{
        int v,w,nex;
    }edge[maxn<<1];
    
    int n,ans,cnt,head[maxn],sz[maxn],mson[maxn],Min,root,size;
    int vis[maxn],t,dis[maxn],num[4];
    
    void adde(int u,int v,int w){
        edge[++cnt].v=v;
        edge[cnt].w=w;
        edge[cnt].nex=head[u];
        head[u]=cnt;
    }
    
    int gcd(int a,int b){
        return b?gcd(b,a%b):a;
    }
    
    void getroot(int u,int fa){
        sz[u]=1,mson[u]=0;
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(vis[v]||v==fa) continue;
            getroot(v,u);
            sz[u]+=sz[v];
            if(sz[v]>mson[u]) mson[u]=sz[v];
        }
        if(size-sz[u]>mson[u]) mson[u]=size-sz[u];
        if(mson[u]<Min) Min=mson[u],root=u;
    }
    
    void getdis(int u,int fa,int len){
        dis[++t]=len;
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(vis[v]||v==fa) continue;
            getdis(v,u,(len+edge[i].w)%3);
        }
    }
    
    void solve(int x,int y,int f){
        t=0;
        getdis(x,0,y);
        num[0]=num[1]=num[2]=0;
        for(int i=1;i<=t;++i)
            ++num[dis[i]];
        ans+=(num[0]-1)*num[0]/2*f;
        ans+=num[1]*num[2]*f;
    }
    
    void fenzhi(int u,int ssize){
        vis[u]=1;
        solve(u,0,1);
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(vis[v]) continue;
            solve(v,edge[i].w%3,-1);
            Min=inf,root=0;
            size=sz[v]<sz[u]?sz[v]:(ssize-sz[u]);
            getroot(v,0);
            fenzhi(root,size);
        }
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            adde(u,v,w%3);
            adde(v,u,w%3);
        }
        Min=inf,root=0,size=n;
        getroot(1,0);
        fenzhi(root,n);
        ans=2*ans+n;
        int tmp1=gcd(ans,n*n);
        ans/=tmp1;
        int tmp2=n*n/tmp1;
        printf("%d/%d
    ",ans,tmp2);
        return 0;
    }
  • 相关阅读:
    Git简介
    git 目录
    版本控制系统介绍
    python 爬虫 基于requests模块发起ajax的post请求
    python 爬虫 基于requests模块发起ajax的get请求
    POJ 2575
    POJ 2578
    POJ 2562
    POJ 2572
    POJ 2560
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11383845.html
Copyright © 2011-2022 走看看