zoukankan      html  css  js  c++  java
  • [MdOI R2] Odyssey 拓扑排序上DP

    [MdOI R2] Odyssey 拓扑排序上DP

    题意

    若正整数(a,b)满足

    • 存在正整数(c),使得(a imes b = c^k)

    则称为数对((a,b))完美数对

    有一个包含(n)个结点,(m)条边的有向无环图,这张图的每条边都有权值和长度两个属性。

    如果一条路径(P)满足:

    • (P)从起点开始经过依次为(e_1,e_2,e_3...e_p)(p)条边,对于任意(1 leq i leq p - 1)(e_i)的权值和(e_{i+1})的权值组成完美数对

    则称为完美路径

    找出图中最长的完美路径,输出长度之和

    [nleq10^5\ m leq 2 imes10^5\ k leq10 \wleq10^5 ]

    分析

    首先处于一个有向无环图,自然希望通过(dp)来解决

    先来处理给出的性质:
    容易发现这里(c)是任意的,(k)是给定的,从唯一分解定理的角度考虑,我们只需要让每个质因子最终都是(k)的倍数即可。

    所以处理方法就是对指数取模(k),要求剩下的指数能够满足,可以发现也是唯一对应的。

    然后就考虑(dp)了,我们发现要到达当前边,必须通过前驱点的边的状态

    (dp[i][val])表示达到点(i),入边的边权为(val),所能得到的最大长度

    [dp[v][val] = max{dp[u][inv(val)] + l} ]

    然后在拓扑序上(dp)即可

    代码

    int n, m, k;
    int indeg[maxn];
    int ans;
    
    unordered_map<int, int> mp[maxn];
    
    int inv(int w) {
        int res = 1;
        for (int i = 2; i * i <= w; i++) {
            int cnt = 0;
            while (w % i == 0) w /= i, cnt++;
            cnt %= k;
            if (cnt) {
                cnt = k - cnt;
                while (cnt--) {
                    res *= i;
                    if (res > 100000) return -1;
                }
            }
        }
        if (w > 1) {
            int cnt = k - 1;
            while (cnt--) {
                res *= w;
                if (res > 100000) return -1;
            }
        }
        return res;
    }
    
    int yu(int w) {
        int res = 1;
        for (int i = 2; i * i <= w; i++) {
            int cnt = 0;
            while (w % i == 0) w /= i, cnt++;
            cnt %= k;
            while (cnt--)
                res *= i;
        }
        if (w > 1 && k != 1) return res * w;
        else return res;
    }
    
    
    struct Edge {
        int v;
        int win, vin, val;
        Edge(int _v, int _val, int _w) {
            v = _v;
            val = _val;
            win = yu(_w);
            vin = inv(_w);
        }
    };
    
    vector<Edge> e[maxn];
    
    void topo() {
        queue<int> q;
        for (int i = 1; i <= n; i++) if (!indeg[i]) q.push(i);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int i = 0; i < e[u].size(); i++) {
                Edge y = e[u][i];
                mp[y.v][y.vin] = max(mp[y.v][y.vin], mp[u][y.win] + y.val);
                ans = max(ans, mp[y.v][y.vin]);
                indeg[y.v]--;
                if (!indeg[y.v]) q.push(y.v);
            }
        }
        printf("%d", ans);
    }
    
    int main() {
        n = readint();
        m = readint();
        k = readint();
        for (int i = 1; i <= m; i++) {
            int a = readint();
            int b = readint();
            int w = readint();
            int v = readint();
            e[a].push_back(Edge(b, v,w));
            indeg[b]++;
        }
        topo();
    }
    
  • 相关阅读:
    原型链
    computed>watch>methods;methods>watch
    rem
    Cookie、Session、Token
    :(){:|:&};:
    js匹配多选框选中项
    sass自备了一系列的函数功能。
    字符串
    ECMAScript6 入门教程记录之-编程风格
    const命令
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13855208.html
Copyright © 2011-2022 走看看