【分析】
问多少对点距离为3的倍数。点分治模板。
【代码】
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#define N 20005
#define M 40005
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pa;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,K,cnt,sum,ans,root;
int b[M],p[N],nextedge[M],w[M];
int f[N],d[N],deep[N],sz[N];
bool flag[N];
void Add(int x,int y,int z)
{
cnt++;
b[cnt]=y;
nextedge[cnt]=p[x];
p[x]=cnt;
w[cnt]=z;
}
void Anode(int x,int y,int z){
Add(x,y,z);Add(y,x,z);
}
void Input_Init()
{
n=read();
for(int i=1;i<n;i++)
{
static int x,y,z;
x=read(),y=read(),z=read()%3;
Anode(x,y,z);
}
}
void getroot(int x,int fa)
{
sz[x]=1,f[x]=0;
for(int i=p[x];i;i=nextedge[i])
{
int v=b[i];
if(v==fa||flag[v]) continue;
getroot(v,x);
sz[x]+=sz[v];
f[x]=max(f[x],sz[v]);
}
f[x]=max(f[x],sum-sz[x]);
root=(f[x]<f[root])?x:root;
}
int Cnt[3];
void getdeep(int x,int fa)
{
Cnt[d[x]]++;
for(int i=p[x];i;i=nextedge[i])
{
int v=b[i];
if(v==fa||flag[v]) continue;
d[v]=(d[x]+w[i])%3;
getdeep(v,x);
}
}
int Cal(int x,int now)
{
d[x]=now;deep[0]=0;
memset(Cnt,0,sizeof(Cnt));
getdeep(x,0);
return Cnt[1]*Cnt[2]*2+Cnt[0]*Cnt[0];
}
void work(int x)
{
ans+=Cal(x,0);
flag[x]=1;
for(int i=p[x];i;i=nextedge[i])
{
int v=b[i];
if(flag[v]) continue;
ans-=Cal(v,w[i]);
sum=sz[v];
root=0;
getroot(v,0);
work(root);
}
}
int main()
{
Input_Init();
sum=f[0]=n;
getroot(1,0);
work(root);
int GCD=__gcd(ans,n*n);
printf("%d/%d\n",ans/GCD,n*n/GCD);
return 0;
}
本文介绍了一道关于计算两点间距离为3的倍数的点分治算法模板题。通过详细阐述算法流程,包括输入初始化、获取重心、计算距离等步骤,并提供了完整的C++代码实现。
430

被折叠的 条评论
为什么被折叠?



