1. 程式人生 > 其它 >洛谷P2634 [國家集訓隊]聰聰可可

洛谷P2634 [國家集訓隊]聰聰可可

題鏈

點分治模板題

#include<bits/stdc++.h> 
using namespace std;
#define ll long long 
#define LL long long 
#define MAXN 9
#define MS 20009

LL n,m;
struct node{
	int to,val;
};
vector<node > vc[MS];
LL ans,sum;
int rt,tr_size;
int sz[MS],w[MS];
int del[MS];
int dis[MS];
int ext[MAXN];
int dismap[MAXN];

void get_rt(int u,int f){
	sz[u] = 1;
	w[u] = 0;
	for(auto &nb:vc[u]){
		int v = nb.to;
		if(v != f && !del[v]){
			get_rt(v,u);
			sz[u] += sz[v];
			w[u] = max(w[u],sz[v]);
		}
	}
	w[u] = max(w[u],tr_size-sz[u]);
	if(w[u] < w[rt]) rt = u;
}

void get_dis(int u,int f){
	dismap[dis[u]%3]++;
	for(auto &nb:vc[u]){
		int v = nb.to;
		int val = nb.val;
		if(v != f && !del[v]){
			dis[v] = ( dis[u]+val ) % 3;
			get_dis(v,u);
		}
	}
}

void cal(int u){
	ext[0]++;
	for(auto &nb:vc[u]){
		int v = nb.to;
		int val = nb.val;
		if(!del[v]){
			for(int i=0;i<3;i++) dismap[i] = 0;
			dis[v] = val % 3;
			get_dis(v,u);
			// 更新答案 
			for(int i=0;i<3;i++){
				ans += dismap[i]*ext[(3-i)%3]*2;
			}
			
			for(int i=0;i<3;i++){
				ext[i] += dismap[i];
			}
		}
	}
	for(int i=0;i<3;i++) ext[i] = 0;
} 

void divide(int u){
	del[u] = 1;
	cal(u);
	for(auto &nb:vc[u]){
		int v = nb.to;
		if(!del[v]){
			w[rt = 0] = tr_size = sz[v];
			get_rt(v,0);
			get_rt(rt,0);
			divide(rt);
		}
	}
}

void solve(){
	cin >> n;
	for(int i=2;i<=n;i++){
		int u,v,val;
		cin >> u >> v >> val;
		val %= 3;
		vc[u].push_back({v,val});
		vc[v].push_back({u,val});
	}
	ans = n ,sum = n*n;
	w[rt = 0] = tr_size = n;
	get_rt(1,0);
	get_rt(rt,0);
	divide(rt);
	
	LL t = __gcd(ans,sum);
	ans /= t ,sum /= t;
	cout << ans << "/" << sum << "\n";
} 

int main(){
	ios::sync_with_stdio(false);
	int ce;
	ce = 1;
//	cin >> ce;
	while(ce--){
		solve(); 
	} 

	return 0;
}