点分治但有改变
统计时统计每棵子树上路径和为X出现的一次和多次的次数,
同时注意删边可用set优化为logN
本题是点分治的第二种写法
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#define Max_N 100005
using namespace std;
typedef set<pair<int, int> >::const_iterator iter;
int tree_size[Max_N];
set<pair<int, int> > E[Max_N];
int compute_subtree_size(int u,int p){
int res=1;
for(iter i=E[u].begin();i!=E[u].end();++i){
if(i->first!=p){
res+=compute_subtree_size(i->first,u);
}
}
return tree_size[u]=res;
}
int b_offset;
int c_offset;
pair<int, int> B[2*Max_N+1];
pair<int, int> C[2*Max_N+1];
void count_partials(int u,int p,int w,int mxw,int mnw){
if(w==mxw||w==mnw){
mxw=max(mxw,w+1);
mnw=min(mnw,w-1);
C[c_offset+w].second++;
}else{
C[c_offset+w].first++;
}
for(iter i=E[u].begin();i!=E[u].end();++i){
if(i->first!=p){
count_partials(i->first,u,w+i->second,mxw,mnw);
}
}
}
long long solve(int u){
int N=compute_subtree_size(u,-1);
int p=-1;
for(;;){
bool seperator=true;
for(iter i=E[u].begin();i!=E[u].end();++i){
if(i->first!=p&&tree_size[i->first]>=N/2){
seperator=false;
p=u;
u=i->first;
break;
}
}
if(seperator)break;
}
b_offset=N;
fill(B,B+2*N+1,make_pair(0,0));
B[b_offset].second=1;
long long result=0;
for(iter i=E[u].begin();i!=E[u].end();++i){
int v=i->first;
c_offset=tree_size[v];
fill(C,C+2*c_offset+1,make_pair(0,0));
count_partials(v,u,i->second,i->second,i->second);
for(int w=-tree_size[v];w<=tree_size[v];++w){
result+=(long long)C[c_offset+w].first*B[b_offset-w].first;
result+=(long long)C[c_offset+w].second*B[b_offset-w].first;
result+=(long long)C[c_offset+w].first*B[b_offset-w].second;
}
result+=(long long)C[c_offset].second*(B[b_offset].second-1);
for(int w=-tree_size[v];w<=tree_size[v];++w){
B[b_offset+w].first+=C[c_offset+w].first;
B[b_offset+w].second+=C[c_offset+w].second;
}
}
for(iter i=E[u].begin();i!=E[u].end();++i){
int v=i->first;
E[v].erase(make_pair(u,i->second));
result+=solve(v);
}
return result;
}
int main(){
ios::sync_with_stdio(false);
int n;cin>>n;
for(int i=1;i<n;i++){
int x,y,z;
cin>>x>>y>>z;
z=z==0?-1:1;
E[x].insert(make_pair(y,z));
E[y].insert(make_pair(x,z));
}
cout<<solve(1)<<endl;
return 0;
}