zoukankan      html  css  js  c++  java
  • [树上DP] I 2019 P2634 [国家集训队]聪聪可可

    求树上简单路径长度为2019倍数的路径条数


     解题思路 :

    二维状态dp[i][j]代表i节点的子树上所有点到i的距离为j的个数

    考虑两点u, v,两点间的贡献为  ans += dp[u][i] * dp[v][(2019 - i - v + 2019) % 2019]; i = 0 - 2018

    此时u的贡献会转移为 dp[u][(i + val(边权)) % 2019] += dp[v][i]; i = 0 - 2018

    所以计算u v时 v的子树必须计算完成 所以递归计算

    对于洛谷P2634 考虑两点和自身点 总答案为上dp计算答案*2+点数即可

    /*
        Zeolim - An AC a day keeps the bug away
    */
      
    //#pragma GCC optimize(2)
    //#pragma GCC ("-W1,--stack=128000000")
    #include <bits/stdc++.h>
    using namespace std;
    #define mp(x, y) make_pair(x, y)
    #define fr(x, y, z) for(int x = y; x < z; ++x)
    #define pb(x) push_back(x)
    #define mem(x, y) memset(x, y, sizeof(x))
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    typedef std::pair <int, int> pii;
    typedef std::vector <int> vi;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f;
    const ll MOD = 386910137;
    const ull P = 13331;
    const int MAXN = 2e5 + 10;
     
    int head[MAXN] = {0}, cnt = 0;
    struct node { int to, val, next; }edge[MAXN];
    void add(int from, int to, int val) { edge[++cnt] = node{to, val, head[from]}; head[from] = cnt; }
    int dp[MAXN][2030];
    int ans = 0;
     
    void init(int n)
    {
        cnt = 0;
        fill(head, head + n + 10, 0);
        for(int i = 1; i <= n; ++i)
            fill(dp[i], dp[i] + 2030, 0);
        ans = 0;
    }
     
    void cal(int now, int fa, int v)
    {
        for(int i = 0; i < 2019; ++i)
            ans += dp[fa][i] * dp[now][(2019 - i - v + 2019) % 2019];
             
        for(int i = 0; i < 2019; ++i)
            dp[now][(i + v) % 2019] += dp[fa][i];
    }
      
    void gao(int now, int fa)
    {  
        dp[now][0] = 1;
         
        for(int it = head[now]; it; it = edge[it].next)
        {
            int to = edge[it].to, v = edge[it].val;
             
            if(to == fa)
                continue;
             
            gao(to, now);
             
            cal(now, to, v);   
        }  
    }
     
    int main()
    { 
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        //freopen("d:out.txt","w",stdout);
        //freopen("d:in.txt","r",stdin);
         
        int n;
         
        while(cin >> n)
        {
            init(n);
            for(int i = 1, x, y, z; i < n; ++i)
            {
                cin >> x >> y >> z;
                add(x, y, z);
                add(y, x, z);
            }
            ans = 0;
            gao(1, 0);
            cout << ans << '
    ';
        }
     
        return 0;
    }
  • 相关阅读:
    centos7 主从dns配置 bind服务
    Linux的启动流程
    shell脚本编程数组
    shell脚本编程进阶
    计划任务
    进程管理
    Linux网络配置
    计算机网络基础
    磁盘存储和文件系统
    软件包管理
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270331.html
Copyright © 2011-2022 走看看