zoukankan      html  css  js  c++  java
  • [国家集训队] 聪聪可可

    算是点分治的模板吧,把每条边都模3归类就可以了。
    模板我是学yyb dalao的。
    计算calc函数的时候有一点改进就是不需要把所有的节点的枚举一遍了,可以直接通过相互关系计算得出qwq。
    至于为什么前面不同的要乘以二呢?大家可以思考一下,原先我们要枚举每个点然后是一个平方的算法,然后自然是值不同的话会被计算两次,值相同的只有一次啦qwq(不理解的话可以模拟一下过程??)
    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 100010
    using namespace std;
    inline int read()
    {
        int f=1,x=0; char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    int n,m,t,tot,root,minr,size;
    int done[MAXN],head[MAXN],s[4],siz[MAXN],num[4];
    struct Edge{int nxt,to,dis;}edge[MAXN<<1];
    inline void add(int from,int to,int dis){edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;}
    inline void get_rt(int x,int fa)
    {
        siz[x]=1;
        int res=0;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==fa||done[v]) continue;
            get_rt(v,x);
            res=max(res,siz[v]);
            siz[x]+=siz[v];
        }
        res=max(res,size-siz[x]);
        if(res<minr) minr=res,root=x;
    }
    inline void get_dep(int x,int fa,int dep)
    {
        s[dep%3]++;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==fa||done[v]) continue;
            get_dep(v,x,dep+edge[i].dis);
        }
    }
    inline void calc(int x,int op,int sum)
    {
        memset(s,0,sizeof(s));
        get_dep(x,x,0);
        if(op)
        {
            num[0]+=2*s[1]*s[2]+s[0]*s[0];
            num[1]+=2*s[0]*s[1]+s[2]*s[2];
            num[2]+=2*s[0]*s[2]+s[1]*s[1];
        }
        else
        {
            sum%=3;
            num[(0+sum)%3]-=2*s[1]*s[2]+s[0]*s[0];
            num[(1+sum)%3]-=2*s[0]*s[1]+s[2]*s[2];
            num[(2+sum)%3]-=2*s[0]*s[2]+s[1]*s[1];
        }
    }
    inline void dfs(int x)
    {
        calc(x,1,0);
        done[x]=1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(done[v]) continue;
            calc(v,0,edge[i].dis*2);
            minr=n,size=siz[v];
            get_rt(v,x);
            dfs(root);
        }
    }
    inline int gcd(int x,int y)
    {
        return y?gcd(y,x%y):x;
    }
    int main()
    {
      
        n=read();
        int u,v,w;
        for(int i=1;i<n;i++)
        {
            u=read(),v=read(),w=read();
            add(u,v,w),add(v,u,w);
        }
        minr=size=n;
        get_rt(1,1);
        dfs(root);
        int x=num[0];
        int y=num[0]+num[1]+num[2];
        int cur=gcd(x,y);
        printf("%d/%d
    ",x/cur,y/cur);
        return 0;
    }
    
    
  • 相关阅读:
    Springboot打jar 包
    mysql 函数
    SFTP的使用
    Java Swing
    消息中间件之ActiveMQ
    对象的四种引用关系
    vs的url传参
    后台管理两级类别
    $.dialog弹层---lhgDialog
    正则小数验证和去除中间空格
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10274231.html
Copyright © 2011-2022 走看看