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;
    }
  • 相关阅读:
    Windows 8实例教程系列 开篇
    qt 开发发布于 windeploy.exe
    qt qoci 测试验证
    vmware vmx 版本不兼容
    qt oracle
    vc qt dll
    QOCIDriver unable to create environment
    qoci 编译完 放置位置 具体根据情况
    calling 'lastError' with incomplete return type 'QSqlError' qsqlquer
    Hbase 操作工具类
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11383845.html
Copyright © 2011-2022 走看看