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;
    }
  • 相关阅读:
    AS将一个项目导入到另一个项目中
    Android Studio出现:Cause: unable to find valid certification path to requested target
    小米手机Toast带app名称
    PopupWindow 点击外部区域无法关闭的问题
    EditText inputType类型整理
    Fragment通过接口回调向父Activity传值
    Android selector一些坑
    Installation failed with message Failed to commit install session 634765663 with command cmd package
    旷视上海研究院机器人方向招聘
    语义SLAM的数据关联和语义定位(四)多目标测量概率模型
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11383845.html
Copyright © 2011-2022 走看看