zoukankan      html  css  js  c++  java
  • P2634 [国家集训队]聪聪可可(点分治)

    题意:给你一颗树,询问路径和是3的倍数的路径有多少条

    思路:日常搬运点分治,这个题其实是运用了取模,三的倍数其实可以转化为对3取模,然后直接点分治

    代码:(一直T,最后发现是getroot时写错了)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int read()
    {
        int x=0,w=1;char ch=getchar();
        while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        if (ch=='-') w=0,ch=getchar();
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return w?x:-x;
    }
    
    const int maxn=20005;
    struct edge
    {
        int to,next,w;
    }a[maxn<<1];
    int n,m,k,head[maxn],cnt;
    int root,sum,vis[maxn],sz[maxn];
    int f[maxn],dep[maxn];
    int ans;
    int t[5];
    int MAX(int x,int y)
    {
        return x>y?x:y;
    }
    int gcd(int x,int y)
    {
        return y==0?x:gcd(y,x%y);
    }
    void addedge(int u,int v,int w)
    {
        a[++cnt].to=v;
        a[cnt].next=head[u];
        a[cnt].w=w;
        head[u]=cnt;
    }
    
    void getroot(int u,int fa)
    {
        sz[u]=1;f[u]=0;
        for(int e=head[u];e;e=a[e].next){
            int v=a[e].to;if(v==fa||vis[v])continue;
            getroot(v,u);
            sz[u]+=sz[v];
            f[u]=MAX(f[u],sz[v]);
        }
        f[u]=MAX(f[u],sum-sz[u]);
        if(f[u]<f[root])root=u;
    }
    void getdeep(int u,int fa)
    {
        t[dep[u]%3]++;
        for(int e=head[u];e;e=a[e].next){
            int v=a[e].to;if(v==fa||vis[v])continue;
            dep[v]=dep[u]+a[e].w;
            getdeep(v,u);
        }
    }
    int calc(int u,int d0)
    {
        dep[u]=d0;t[0]=t[1]=t[2]=0;
        getdeep(u,0);
        return t[0]*t[0]+2*t[1]*t[2];
    }
    void solve(int u)
    {
        ans+=calc(u,0);vis[u]=1;
        for(int e=head[u];e;e=a[e].next){
            int v=a[e].to;if(vis[v])continue;
            ans-=calc(v,a[e].w);
            sum=sz[v];root=0;
            getroot(v,0);
            solve(root);
        }
    }
    int main()
    {
        n=read();
        for(int i=1;i<n;++i){
            int u=read(),v=read(),w=read();
            addedge(u,v,w);
            addedge(v,u,w);
        }
        f[0]=sum=n;
        getroot(1,0);
        solve(root);
        int as=gcd(ans,n*n);
        ans/=as;
        printf("%d/%d
    ",ans,n*n/as);
        return 0;
    }
  • 相关阅读:
    winform 计算器
    js 特效代码网址
    js 动图效果
    计算器 练习
    html frameset 练习
    SQL 仓库管理练习题
    数据库存取图片
    数据库查询Database中的表
    面向对象练习
    C#函数与SQL储存过程
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9775528.html
Copyright © 2011-2022 走看看