zoukankan      html  css  js  c++  java
  • 2019 湖南省赛 I题 2019 (树形DP???)

    题目链接
    当时比赛的时候没有写出来,当时,换根DP不太熟练,所以没怎么,往那方面去想,想了一个类似树形DP,结果还是没写出来。
    然后,仔细学了会换根DP,后面的沈阳网络赛就碰到一道换根DP的题,喜提一发PE AC
    但是,还是想用自己最初的那个想法去做,并且A掉
    牛客网1号就能开了省赛的复现赛 (????),国庆嘛,太高兴了,然后到今天才去写,啦啦啦啦

    想法:
    在这里插入图片描述
    如上图,红色表示树的组成部分,蓝色表示路径的种类
    在一棵子树中,将路径分为三种:
    (1) 只有一条边
    (2) 子树的根节点是路径的端点(至少由两条边组成)
    (3) 子树的根节点不是路径的端点,(至少由两条边组成)
    对于三种路径的答案的统计的方法:
    令根节点是u, u的一个子节点是v, val 是边(u, v)的权值
    (1) 在输入的时候,直接判断下就好了
    (2) 就是节点v 所控制的子树中,能与val组成符合答案的个数
    (3) 如图上的(3) 就是dp[5][3]*dp[6][2017]
    代码中会有详细的注释

    #include <bits/stdc++.h>
    const int maxn = 2e4+50;
    const int maxm = 2020;
    using namespace std;
    typedef long long ll;
    struct note{
        int to, w;
        note(){}
        note(int to1, int w1){
            to = to1, w = w1;
        }
    };
    vector <note> maps[maxn];
    int  n, in[maxn];
    ll ans, dp[maxn][maxm], tmp[maxm];
    // dp[u][i] 表示节点u控制的子树中,以u为端点的路径,值为i的种类数
    
    
    void dfs(int u, int fa, int val){
        //u dfs的当前节点, fa  节点u的父节点   val  边(u, fa)的权值
        for(int i=0; i<2019; i++)       //初始化
            dp[u][i] = 0;
        for(int i=0, len=maps[u].size(); i<len; i++){
            int v = maps[u][i].to, w = maps[u][i].w;
            if(v != fa){
                dfs(v, u, w);
                for(int j=0; j<2019; j++){
                    ans += dp[u][j]*dp[v][(2019-j)%2019];   //由(3)产生的答案数
                    dp[u][j] += dp[v][j];   //把子树的统计结果累加上去
                }
            }
        }
        if(in[u] != 1 && u != fa)
            ans += dp[u][(2019-val)%2019];  //由(2)产生的答案数,但是不能统计叶子节点和整棵树的根节点
        for(int i=0; i<2019; i++)
            tmp[(i+val)%2019] = dp[u][i];
        for(int i=0; i<2019; i++)
            dp[u][i] = tmp[i];  
        dp[u][val%2019]++;
    }
    
    int main()
    {
        while(scanf("%d", &n)!=EOF){
            ans = 0;
            for(int i=0; i<=n; i++)
                maps[i].clear(), in[i] = 0;
            for(int i=1, a, b, c; i<n; i++){
                scanf("%d%d%d", &a, &b, &c);
                maps[a].push_back(note(b, c));
                maps[b].push_back(note(a, c));
                in[a]++, in[b]++;
                if(c%2019 == 0)
                    ans++;      //由(1)产生的答案数
            }
            dfs(1, 1, 2019);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
    

    不懂的,可以和我交流

  • 相关阅读:
    CCF-CSP题解 201509-4 高速公路
    CCF-CSP题解 201403-4 无线网络
    CCF-CSP题解 201512-4 送货
    2019年9月10日
    53. 最大子序和
    54. 螺旋矩阵
    59. 螺旋矩阵 II
    61. 旋转链表
    62. 不同路径
    70. 爬楼梯
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337328.html
Copyright © 2011-2022 走看看