Luo Gu P2634 [National Team] Cong Cong cocoa tree DP solution to a problem

This is my first post with markdown to write a blog, format a bad please forgive me.

Daily questions day63 punch

Analysis

This question Correct answer is dotted rule, but I found the practice of tree-DP, so I wrote a tree DP.
\ [Dp [i] [0/1/2 ] i represents a sub-tree of how many points the distance i die 3 with a remainder of 0,1,2 \]
First, think about how to transfer, for each i , it can be with DP [from] [(J + Val). 3%] + DP = [to] [J] ( J is the case enumeration) to update the root answer, since the distance of each sub-tree root in the new the will + Val .

Then how to think record the answer, how many legitimate state solution to calculate the current sub-tree with the multiplication principle of state with all sub-trees counted prior to the formation, namely ANS + = dp [to] [J] \ (\ Times \) dp [ from] [((- J-Val) +. 3. 3%). 3%] \ (\ Times \) 2 . In this case, you as a reader will ask, why is ((-j-Val) 3 + 3%) 3% ? Because the current state of the sub-tree and counted before all subtrees of the state and to satisfy the (X + Y)%. 3 = 0 , so it should be . 3-J-Val , . 3 can erase about, \ (J> 0 \ Val &> 0 \) , stars ((-j-Val) +. 3. 3%). 3% .

Precautions:

1. Because there may be a sub-tree, it will dp [from] [0] = 1 to avoid this.

2. Since the number of (point two candidates) ordered, so when calculating the answer \ (\ Times 2 \) .

3. because the answer legitimate point when the two coincide, so in the end you want to \ (the n-ANS + = \) .

4. Do not forget about the output points.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define maxn 20000+10
#define rep(i,s,e) for(register int i=s;i<=e;++i)
#define dwn(i,s,e) for(register int i=s;i>=e;--i)
using namespace std;
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
    return f*x;
}
void write(int x)
{
    if(x<0) {putchar('-'); x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n,cnt,ans;
int head[maxn];
int dp[maxn][3];
struct node
{
    int v,w,nex;
}edge[2*maxn];
inline void add(int x,int y,int z)
{
    edge[++cnt].v=y;
    edge[cnt].w=z;
    edge[cnt].nex=head[x];
    head[x]=cnt;
}
void tree_dp(int from,int father)
{
    dp[from][0]=1;
    for(int i=head[from];i;i=edge[i].nex)
    {
        int to=edge[i].v,val=edge[i].w%3;
        if(to==father) continue;
        tree_dp(to,from);
        rep(j,0,2)
            ans+=dp[to][j]*dp[from][((-j-val)%3+3)%3]*2;
        rep(j,0,2)
            dp[from][(j+val)%3]+=dp[to][j];
    }
}
signed main()
{
    n=read();
    rep(i,1,n-1)
    {
        int x=read(),y=read(),z=read();
        add(x,y,z);
        add(y,x,z);
    }
    tree_dp(1,-1);
    ans+=n;
    int fz=ans,fm=n*n;
    write(fz/__gcd(fz,fm));
    putchar('/');
    write(fm/__gcd(fz,fm));
    return 0;
}

If mistakes please correct me big brother(Anyway, I do not know what that means treatise)

Guess you like

Origin www.cnblogs.com/handsome-zyc/p/12111463.html