之前用树形dp写的,这次用点分治写一下,不解释~
#include <bits/stdc++.h>
using namespace std;
const int N=2e4+500;
const int mod=2019;
struct Tree{
int to,val;
};
vector<Tree>v[N];
bool vis[N];
int sz[N],f[N],sum,root;
long long ans=0;
map<int,int>s;
void f_root(int u,int fa)
{
sz[u]=1;f[u]=0;
for(int i=0;i<(int)v[u].size();i++)
{
int son=v[u][i].to;
if(son==fa||vis[son]) continue;
f_root(son,u);sz[u]+=sz[son];
f[u]=max(f[u],sz[son]);
}f[u]=max(f[u],sum-f[u]);
if(f[root]>f[u]) root=u;
}
void Cnt_node(int u,int fa,int cnt)
{
for(int i=0;i<(int)v[u].size();i++)
{
int son=v[u][i].to;int Val=v[u][i].val;
int pos=(cnt+Val)%mod;
if(son==fa||vis[son]) continue;
s[pos]++;
Cnt_node(son,u,pos);
}
}
void Cnt_ans(int u,int fa,int cnt)
{
for(int i=0;i<(int)v[u].size();i++)
{
int son=v[u][i].to;int Val=v[u][i].val;
int pos=(cnt+Val)%mod;
if(son==fa||vis[son]) continue;
if(pos%mod==0) ans++;ans+=s[(mod-(pos)%mod)%mod];
Cnt_ans(son,u,pos);
}
}
void cal(int u,int fa,int cnt)
{
for(int i=0;i<(int)v[u].size();i++)
{
int son=v[u][i].to;int Val=v[u][i].val;
int pos=cnt+Val;
if(son==fa||vis[son]) continue;
if(Val%mod==0) ans++;ans+=s[(mod-(Val%mod))%mod];
Cnt_ans(son,u,pos);
s[Val]++;
Cnt_node(son,u,pos);
}
}
void solve(int u)
{
cal(u,0,0);
s.clear();vis[u]=true;
for(int i=0;i<(int)v[u].size();i++)
{
int son=v[u][i].to;
if(vis[son]) continue;
root=0;sum=sz[son];
f_root(son,u);
solve(son);
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
s.clear();ans=0;
for(int i=1;i<=n;i++) v[i].clear();
for(int i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
v[a].push_back({b,c});
v[b].push_back({a,c});
}root=0;f[0]=n,sum=n;
memset(vis,false,sizeof vis);
f_root(1,0);
solve(root);
printf("%lld\n",ans);
}
return 0;
}

京公网安备 11010502036488号