[BZOJ 2152][Luogu P2634]聪聪可可

Posted trisolaris

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 2152][Luogu P2634]聪聪可可相关的知识,希望对你有一定的参考价值。

[BZOJ 2152][Luogu P2634]聪聪可可

 

<题意概括>

给定一棵树,求树上距离为3的倍数的点对对数

 

<做法>

有关树上路径统计的问题当然可以想到点分治

与普通点分治一样的做法

在统计路径时使用$Ans_{i}$来储存$Length\equiv i(mod3)$的路径条数

则易知答案数为$Ans_{0}^{2}+2*Ans_{1}*Ans_{2}$$(0+0\equiv 1+2\equiv 2+1\equiv 0(mod3))$

 

<Code>

技术分享图片
#include<cstdio>
#include<cstring>
#define Fast register
#define INF 2147483647
inline int gcd(const int&x,const int&y){return y?gcd(y,x%y):x;}
inline char Getchar(){
    static char BUF[16384],*S=BUF,*T=BUF;
    return(S==T)&&(T=(S=BUF)+fread(BUF,1,16384,stdin),S==T)?EOF:*S++;
}
inline int Getint(){
    Fast int s=0;Fast char c=Getchar();
    while(c<48||c>57)c=Getchar();
    while(c>47&&c<58)s=s*10+c-48,c=Getchar();
    return s;
}
#define Mod(x) ((x)%3)
#define Max(x,y) (x>y?x:y)
int Distance[20001];
int Ans[3];
int Answer;
int root;
int Recent_Node;
int MaxSize[20001];
int Size[20001];
bool vis[20001];
struct Edge{
    int to,v;Edge*next;
    Edge(const int&T,const int&V,Edge*&N):to(T),v(V),next(N){}
}*Front[20001];
#define AddEdge(F,T,V) Front[F]=new Edge(T,V,Front[F])
inline void FindBarycenter(const int&now,const int&Fa){
    Size[now]=1;MaxSize[now]=0;
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(!vis[o->to]&&o->to!=Fa){
            FindBarycenter(o->to,now);
            Size[now]+=Size[o->to];
            MaxSize[now]=Max(MaxSize[now],Size[o->to]);
        }
    }
    MaxSize[now]=Max(MaxSize[now],Recent_Node-Size[now]);
    if(MaxSize[now]<MaxSize[root])root=now;
}
inline void Cal_Dis(const int&now,const int&Fa){
    ++Ans[Mod(Distance[now])];
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(!vis[o->to]&&o->to!=Fa){
            Distance[o->to]=Mod(Distance[now]+o->v);
            Cal_Dis(o->to,now);
        }
    }
}
inline int Calculate(const int&now,const int&DisNow){
    Ans[0]=Ans[1]=Ans[2]=0;
    Distance[now]=Mod(DisNow);
    Cal_Dis(now,0);
    return Ans[0]*Ans[0]+(Ans[1]*Ans[2]<<1);
}
inline void Slove(const int&now){
    Answer+=Calculate(now,0);vis[now]=true;
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(!vis[o->to]){
            root=0;Recent_Node=Size[o->to];
            Answer-=Calculate(o->to,o->v);
            FindBarycenter(o->to,now);
            Slove(root);
        }
    }
}
int main(){
    Fast int N=Getint(),x,y,w;
    for(Fast int i=1;i<N;++i){
        x=Getint(),y=Getint(),w=Getint();
        AddEdge(x,y,Mod(w));AddEdge(y,x,Mod(w));
    }
    MaxSize[root=0]=INF;Recent_Node=N;
    FindBarycenter(1,0);Slove(root);
    Fast int GCD=gcd(N*N,Answer);
    printf("%d/%d",Answer/GCD,N*N/GCD);
    return 0;
}
[BZOJ 2152][Luogu P2634]聪聪可可

以上是关于[BZOJ 2152][Luogu P2634]聪聪可可的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2152 「国家集训队」聪聪可可(点分治)BZOJ计划

BZOJ 2152 「国家集训队」聪聪可可(点分治)BZOJ计划

题解:luogu P2634 [国家集训队]聪聪可可

BZOJ 2152 聪聪可可

bzoj2152 聪聪可可

bzoj 2152: 聪聪可可