# 亚洲区预赛(沈阳)网络赛 D . Fish eating fruit (点分治)

State Z is a underwater kingdom of the Atlantic Ocean. This country is amazing. There are nnn cities in the country and n−1n-1n−1 undirected underwater roads which connect all cities.

In order to save energy and avoid traffic congestion, the king promulgated a series of traffic regulations:

  1. Residents have to travel on fish!

  2. Residents need to feed the fish before you start your trip!The amount of food you feed the fish should be exactly the total distance of your journey.

  3. What kind of food to feed depends on the total distance of your journey!Total distance is a multiple of three. You should feed the fish with Durian. Total distance modulus 333 equaling 111. It should be Papaya.Total distance modulus 333 equaling 222. It should be Avocado!!!

Sure, fish like to eat these fruits very much.

Today is the first day of the king's decree. Because the residents here are not good at mathematics, they don't know how much fruit they need to give fish to go to other cities. So the king give an order to the energy minister Ynaonlctrm From all cities to all cities directly, which means that he will make n∗(n−1)n*(n-1)n∗(n−1) trips.

For example, A - (5 mile) - B - (5 mile) - C, he needs to run the fish, starting at A, passing B, finally arriving C (papaya 10 kg), also he needs to start at C and end at A (papaya 10 kg). Indirect passage is useless. "I've passed City B, my dear emperor." "Oh! It's no use! Not directly! People in cities will never know how much the fish need to eat! The fish will surely die!!! You also need to take several trips which start at B or end with B!" The Emperor said.

It's really a tough task. Can you help him figure out how much fruit he needs to prepare for the emperor's mission?

Input

Multiple input!

Fist line is NNN. next N−1N-1N−1 line has three integer aaa, bbb and ccc. It represent city aaa and city bbb is connected by a road of ccc nautical miles. (1<n≤1041<n \le 10^41<n≤104, 0≤a,b<n0 \le a,b<n0≤a,b<n, 1≤c<1051 \le c<10^51≤c<105, ∑n≤105\sum{n} \le 10^5∑n≤105)

Output

For each data, output three number, the amount of Durian, Papaya and Avocado he need. (the result could be very large, please output the result mod 109+710^9+7109+7)

样例输入1复制

5
0 1 2
0 2 3
0 3 7
0 4 6

样例输出1

54 60 30

样例输入2

8
4 7 1
7 5 1
4 6 1
6 3 1
5 2 1
2 1 1
7 0 1

样例输出2

48 54 48

题目大大意 : 输入一棵树, 输出树上两点之间距离和模3等于 0, 1, 2的长度之和对 1e9 + 7取模后的结果

思路 : 点分治思想, 分治过程中除了维护一些必要的变量(根,树的大小,重心, 各点到根的距离等等)之外,最主要的是维护路径当中模3等于0, 1, 2的次数和总长度, 每次更新的时候先对第一条链进行更新, 直接判断他模3等于几, 然后判断之前保存的点和该路径的和的情况, 共有9种, 分别是0 + 0, 0 + 1, 0 + 2, 1 + 0, 1 + 1, 1 + 2, 2 + 0, 2 + 1, 2 + 2, 对应各个情况进行相加取模就好, 比如一条路径a和两个路径b, c的和模3 = x, 那么x的答案就要加上路径b + 路径c + 次数2 * 路径a。

Accepted code

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 2e5 + 100;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }

struct Edge
{
	ll v, w, next;
}e[MAXN << 1];
ll head[MAXN], n, m, cnt;
ll s_num[MAXN], maxp[MAXN], cut[MAXN], rt, rt_num;
ll res[MAXN], dis[MAXN], dp[5], q[MAXN];
bool vis[MAXN], judge[MAXN];
ll ai, bi, ci;
void init() {
	MEM(head, -1); MEM(vis, 0); MEM(judge, 0);
	MEM(dis, 0); MEM(cut, 0); 
	cnt = 0, ai = bi = ci = 0;
}
void add(ll from, ll to, ll wi) {
	e[++cnt].v = to;
	e[cnt].w = wi;
	e[cnt].next = head[from];
	head[from] = cnt;
}
void rt_dfs(ll x, ll fa) {
	s_num[x] = 1, maxp[x] = 0;
	for (ll i = head[x]; i != -1; i = e[i].next) {
		ll vi = e[i].v;
		if (vis[vi] || vi == fa) continue;
		rt_dfs(vi, x);
		s_num[x] += s_num[vi];
		Max(maxp[x], s_num[vi]);
	}
	Max(maxp[x], rt_num - s_num[x]);
	if (maxp[x] < maxp[rt]) rt = x;
}
void dfs(ll x, ll fa) {
	res[++res[0]] = dis[x];
	for (ll i = head[x]; i != -1; i = e[i].next) {
		ll vi = e[i].v;
		if (vi == fa || vis[vi]) continue;
		dis[vi] = dis[x] + e[i].w;
		dfs(vi, x);
	}
}
void Calc(ll x) {
	for (ll i = head[x]; i != -1; i = e[i].next) {
		ll vi = e[i].v;
		if (vis[vi]) continue;
		res[0] = 0, dis[vi] = e[i].w;
		dfs(vi, x);
		for (ll j = res[0]; j > 0; j--) {  // 核心部分
			ll scnt = res[j] % 3;  // 单链更新
			if (scnt == 0) ai = ((ai % MOD) + 2 * (res[j] % MOD)) % MOD;
			else if (scnt == 1) bi = ((bi % MOD) + 2 * (res[j] % MOD)) % MOD;
			else if (scnt == 2) ci = ((ci % MOD) + 2 * (res[j] % MOD)) % MOD;
			for (ll k = 0; k < 3; k++) {  // 9种情况
				ll stot = (res[j] % 3 + k) % 3;
				if (q[k] > 0) {
					if (stot % 3 == 0) ai = ((ai % MOD) + 2 * ((dp[k] % MOD) + (q[k] * res[j])) % MOD) % MOD;
					else if (stot % 3 == 1) bi = ((bi % MOD) + 2 * ((dp[k] % MOD) + (q[k] * res[j])) % MOD) % MOD;
					else if (stot % 3 == 2) ci = ((ci % MOD) + 2 * ((dp[k] % MOD) + (q[k] * res[j])) % MOD) % MOD;
				}
			}
		}
		for (ll j = res[0]; j > 0; j--)
			dp[res[j] % 3] += res[j], q[res[j] % 3]++;
	}
	for (ll i = 0; i < 3; i++) dp[i] = 0, q[i] = 0;
}
void Solve(ll x) {
	vis[x] = judge[0] = true; Calc(x);
	for (ll i = head[x]; i != -1; i = e[i].next) {
		ll vi = e[i].v;
		if (vis[vi]) continue;
		rt_num = s_num[vi], maxp[rt = 0] = INF;
		rt_dfs(vi, x); Solve(rt);
	}
}

int main()
{
	while (~sc("%lld", &n)) {
		init();
		for (ll i = 1; i < n; i++) {
			ll ui, vi, wi;
			sc("%lld %lld %lld", &ui, &vi, &wi);
			add(ui, vi, wi); add(vi, ui, wi);
		}
		rt_num = n, maxp[0] = INF; rt_dfs(1, 1);
		Solve(rt);
		printf("%lld %lld %lld\n", ai, bi, ci);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值