#C241011A. 点分治
标签(Label)
点分治
模板
网址(Website)
题目详情 - 【NOI模板】树分治 - 点分治 - 聪聪可可「国家集训队」 - Super
练习题: #C241010B. 旅游
题解(Solution)
代码实现的时候有几个注意的点:
- 子连通块大小不要直接用 $siz[to]$ ,在访问父亲的连通块的时候会出问题。
代码(Code)
#include<bits/stdc++.h>
#include<vector>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define P pair<int,int>
#define x first
#define y second
inline int rd(){
char c;bool f=false;while(!isdigit(c=getchar()))f=c=='-';int x=c^48;
while(isdigit(c=getchar())){x=(((x<<2)+x)<<1)+(c^48);}return f?-x:x;
}const int inf = 0x3f3f3f3f;
const int N = 201234;
bool ST;
vector<P> ft[N];
int n,zi,mu,root,maxx;
int sub[N],siz[N];
bitset<N> vst;
inline void dfs_root(int x,int fa,int sum){
siz[x] = 1;
int s=0;
for(auto p:ft[x]){
int y = p.x;
if(y==fa || vst[y]) continue;
dfs_root(y,x,sum);
siz[x] += siz[y];
s = max(s, siz[y]);
}s = max(s, sum-siz[x]);
if(s < maxx) maxx = s,root=x;
}
int dis[N],dep[N],tot;
inline void dfs_dis(int x,int fa){
dep[++tot] = dis[x]%3;
for(auto p:ft[x]){
int y = p.x, v = p.y;
if(y==fa || vst[y]) continue;
dis[y] = dis[x]+v;
dfs_dis(y,x);
}
}
inline int cal(int l,int r){
array<int,3> way = {0,0,0};
For(i,l,r) way[dep[i]]++,assert(dep[i]<3);
return way[0]*way[0] + way[1]*way[2]*2;
}
inline int calc(int x){
int res = 0;tot = 0;
dep[++tot] = dis[x] = 0;
for(auto p:ft[x]){
int y = p.x, v = p.y;
if(vst[y]) continue;
int l = tot+1;
dis[y] = dis[x]+v;
dfs_dis(y,x);
int r = tot;
res -= cal(l,r);
}
res += cal(1,tot);
return res;
}
inline void devide(int x){
vst[x] = true;
zi += calc(x);
for(auto p:ft[x]){
int y = p.x;
if(vst[y]) continue;
sub[root = 0] = N;
maxx=siz[y];
dfs_root(y,x,siz[y]);
devide(root);
}
}
int g(int a,int b){
if(!b) return a;
return g(b,a%b);
}
void solve(){
n = rd();For(i,1,n-1){
int x = rd(), y = rd(), v = rd();
ft[x].emplace_back(y,v);
ft[y].emplace_back(x,v);
}mu = n*n;
sub[root = 0] = N;
maxx=n;
dfs_root(1,0,n);
devide(root);
int gg = g(zi,mu);
printf("%d/%d\n",zi/gg,mu/gg);
}
bool ED;
signed main(){
cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
int T = 1, Tim = clock();
while(T--) solve();
return cerr<<"TIME:"<<(clock()-Tim)/1000.,0;
}