luogu2634 聪聪可可

点分治裸题

#include <iostream>
#include <cstdio>
using namespace std;
int n, uu, vv, ww, ans, cnt, hea[20005], rot, gra[20005], sze, qwq[5];
int siz[20005], gcd;
bool vis[20005];
struct Edge{
	int too, nxt, val;
}edge[40005];
void add_edge(int fro, int too, int val){
	edge[++cnt].nxt = hea[fro];
	edge[cnt].too = too;
	edge[cnt].val = val;
	hea[fro] = cnt;
}
void getRoot(int x, int f){
	siz[x] = 1;
	gra[x] = 0;
	for(int i=hea[x]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(t==f || vis[t])	continue;
		getRoot(t, x);
		siz[x] += siz[t];
		gra[x] = max(gra[x], siz[t]);
	}
	gra[x] = max(gra[x], sze-siz[x]);
	if(gra[rot]>gra[x])	rot = x;
}
void getDeep(int x, int fa, int dis){
	qwq[dis]++;
	for(int i=hea[x]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(!vis[t] && t!=fa)
			getDeep(t, x, (dis+edge[i].val)%3);
	}
}
int calc(int x, int fa, int dis){
	qwq[0] = qwq[1] = qwq[2] = qwq[3] = 0;
	getDeep(x, fa, dis%3);
	return qwq[0]*qwq[0] + 2 * qwq[1]*qwq[2];
}
void work(int x){
	vis[x] = true;
	ans += calc(x, x, 0);
	for(int i=hea[x]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(vis[t])	continue;
		ans -= calc(t, x, edge[i].val);
		rot = 0;
		sze = siz[t];
		getRoot(t, 0);
		work(rot);
	}
}
int getGcd(int x, int y){
	return !y?x:getGcd(y, x%y);
}
int main(){
	cin>>n;
	for(int i=1; i<n; i++){
		scanf("%d %d %d", &uu, &vv, &ww);
		add_edge(uu, vv, ww);
		add_edge(vv, uu, ww);
	}
	gra[0] = 0x3f3f3f3f;
	rot = 0;
	sze = n;
	getRoot(1, 0);
	work(rot);
	gcd = getGcd(ans, n*n);
	printf("%d/%d\n", ans/gcd, n*n/gcd);
	return 0;
}
posted @ 2018-01-07 20:02  poorpool  阅读(85)  评论(0编辑  收藏  举报