Solution - P2634 [国家集训队] 聪聪可可

宏定义展开的锅。

思路

极简点分治。

思路显然,每次到的时候算贡献在上传就行了。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 20004
using namespace std;

int to[N<<1], val[N<<1], nxt[N<<1], head[N], gsiz;
#define mkarc(u,v,w) (++gsiz, to[gsiz]=v, val[gsiz]=w, nxt[gsiz]=head[u], head[u]=gsiz)
int dp[N][3];
int n, ans;

#define mod(m) (((m)%3+3)%3)
inline int gcd(rint a, rint b){return b ? gcd(b, a%b) : a;}

inline void dfs(rint u, rint fa){
	dp[u][0] = 1;
	for(rint i = head[u]; i; i = nxt[i]){
		rint v = to[i];
		if(v == fa) continue;
		dfs(v, u);
		for(rint m = 0; m < 3; ++m) ans += (dp[v][m]*dp[u][mod(-m-val[i])])*2;
		for(rint m = 0; m < 3; ++m) dp[u][mod(m+val[i])] += dp[v][m];
	}
	return;
}

int main(){
	scanf("%d", &n);
	for(rint i = 1; i < n; ++i){
		rint u, v, w;
		scanf("%d %d %d", &u, &v, &w), w = mod(w);
		mkarc(u, v, w), mkarc(v, u, w);
	}
	dfs(1, 0);
	rint a = ans+n, b = n*n, d = gcd(a, b);
	printf("%d/%d", a/d, b/d);
	return 0;
}

/*
5
1 2 1
1 3 2
1 4 1
2 5 3

*/

posted @ 2025-05-17 20:28  Hootime  阅读(21)  评论(0)    收藏  举报