题目链接:https://nanti.jisuanke.com/t/41403
题目截图:
解题思路:看到题目就可以看出是一道树形DP的题。每次dfs遍历所有的值,维护的当前节点往下有多少种0,1,2的个数和贡献,然后向上递推就好了。而且这种计数的,就需要维护一个相当于前缀和的东西,防止重复计算。最后就要把答案乘个2就是结果了。而且每次dfs遍历的时候都需要计算一下以这个节点为根的经过当前节点的答案有那些。这个可以直接3*3的暴力就好了。
代码如下:
#include<bits/stdc++.h>
#define FRD freopen("in.txt", "r", stdin)
#define __ctz(x) __builtin_ctz(x) //返回二进制下末尾有几个零
#define __ffs(x) __builtin_ffs(x) //返回二进制下最后一个1的位置,从1开始
#define __max_elenment *max_element //返回一个数组的最大值,参数是数组的起始位置和结束位置
#define __min_elenment *min_element //返回一个数组的最大值,参数是数组的起始位置和结束位置
#define ms(x) memset(x,0,sizeof(x))
#define lowbit(x) x&(-x)
#define pb push_back
#define mk make_pair
#define all(x) x.begin(),x.end()
#define lson (id<<1)
#define rson (id<<1|1)
#define fi first
#define se second
using namespace std;
typedef long long int LL;
typedef pair<LL,LL> pll;
const LL INF = 1e18;
const int N = 1e5+7;
const int MOD = 1e9+7;
constexpr int mul(int a, int b) { return 1LL * a * b % MOD; }
template<typename... T>
constexpr int mul(int a, int b, T... t) { return mul(mul(a, b), t...); }
inline int read() {char ch=getchar();int x=0,f=1;while(ch<'0'||ch>'9') {if(ch == '-') f = -1;ch = getchar();}while('0'<=ch&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
inline LL readl() {char ch=getchar();LL x=0,f=1;while(ch<'0'||ch>'9') {if(ch == '-') f = -1;ch = getchar();}while('0'<=ch&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
int n;
LL cnt[3][N],cost[3][N],ans[3];
struct Node{
int v;
LL c;
};
vector<Node> G[N];
void dfs(int u, int fa) {
LL now_cnt[3], now_cost[3];
ms(now_cnt); ms(now_cost);
for (auto e:G[u]) {
int v = e.v;
if (v == fa) continue;
dfs(v,u);
now_cnt[e.c%3]++;
now_cost[e.c%3] += e.c;
for (int j = 0; j < 3; j++) {
int tmp = (e.c+j)%3;
now_cnt[tmp] = (now_cnt[tmp]+cnt[j][v])%MOD;
now_cost[tmp] = (now_cost[tmp]+cost[j][v]+e.c*cnt[j][v])%MOD;
}
for (int j = 0; j < 3; j++) {
cnt[j][v] = now_cnt[j];
cost[j][v] = now_cost[j];
now_cnt[j] = now_cost[j] = 0;
}
for (int i = 0; i < 3; i++) {
ans[i] = (ans[i]+cost[i][v]);
for (int j = 0; j < 3; j++) {
int tmp = (i+j)%3;
ans[tmp] = (ans[tmp]+cost[i][v]*cnt[j][u]+cnt[i][v]*cost[j][u])%MOD;
}
}
for (int j = 0; j < 3; j++) {
cnt[j][u] = (cnt[j][u]+cnt[j][v])%MOD;
cost[j][u] = (cost[j][u]+cost[j][v])%MOD;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
int startTime = clock();
FRD;
#endif
while (~scanf("%d",&n)) {
for (int i = 1; i < n; i++) {
int u = read(), v = read(), c = read();
G[u].pb((Node){v,c});
G[v].pb((Node){u,c});
}
dfs(0,0);
printf("%lld %lld %lld\n",ans[0]*2%MOD,ans[1]*2%MOD,ans[2]*2%MOD);
ms(ans);
for (int i = 0; i < n; i++) {
G[i].clear();
for (int j = 0; j < 3; j++) {
cnt[j][i] = cost[j][i] = 0;
}
}
}
#ifndef ONLINE_JUDGE
printf("Time = %dms\n", clock() - startTime);
#endif
return 0;
}