• SCUT


    好像原题是这个?https://www.cnblogs.com/kanchuang/p/11120052.html
    这个有解释:https://blog.csdn.net/wddwjlss/article/details/82081754

    原题是这个:https://www.luogu.org/problem/P1144

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MOD = 1e5 + 3, MAXN = 1e6 + 5;
    const int INF = 1e9;
    
    vector<int> e[MAXN];
    inline void add_edge(int u, int v) {
        e[u].emplace_back(v);
        e[v].emplace_back(u);
    }
    
    bool vis[MAXN];
    int dis[MAXN], ans[MAXN];
    priority_queue<pair<int, int> > pq;
    
    void Dijkstra(int n, int s) {
        for(int i = 1; i <= n; i++)
            dis[i] = INF;
        dis[s] = 0, ans[s] = 1, pq.push({0, s});
        while(!pq.empty()) {
            int u = pq.top().second;
            pq.pop();
            if(vis[u])
                continue;
            vis[u] = 1;
            for(auto v : e[u]) {
                if(!vis[v] && dis[v] > dis[u] + 1) {
                    dis[v] = dis[u] + 1;
                    ans[v] = ans[u];
                    pq.push({-dis[v], v});
                } else if(!vis[v] && dis[v] == dis[u] + 1) {
                    ans[v] = (ans[v] + ans[u]) % MOD;
                }
            }
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            add_edge(u, v);
        }
        Dijkstra(n, 1);
        for(int i = 1; i <= n; ++i)
            printf("%d
    ", ans[i]);
    }
    

    询问从1节点开始的最短路的种类数。

    首先连接两个点之间的不是最短的路一定是没有用的。所以至多每种d就n/d条边,同样的直接叠加条数,计数时乘法叠加路径数。

    在dijkstra的同时,要是更新了就清空,否则相等就继续计数。

    图论知识太缺乏。

    哈哈哈我居然能过!

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int INF = 0x3f3f3f3f;
    
    const int MAXN = 5e4 + 5;
    const int MAXM = 1400000 + 5;
    
    struct Edge {
        int v, w, k, next;
        Edge(int v = 0, int w = 0, int k = 0): v(v), w(w), k(k) {}
    };
    
    int cnt_edge;
    int head[MAXN];
    Edge edge[MAXM];
    
    inline void init_graph(int n) {
        cnt_edge = 0;
        memset(head + 1, 0, sizeof(head[0])*n);
    }
    
    inline void add_edge(int u, int v, int w, int k) {
        cnt_edge++;
        edge[cnt_edge].v = v;
        edge[cnt_edge].w = w;
        edge[cnt_edge].k = k;
        edge[cnt_edge].next = head[u];
        head[u] = cnt_edge;
    }
    
    bool vis[MAXN];
    int dis[MAXN];
    int ans[MAXN];
    
    struct Edge_node {
        int v, w;
        Edge_node(int v = 0, int w = 0): v(v), w(w) {}
        bool operator<(const Edge_node &e)const {
            return w > e.w;
        }
    };
    
    const int MOD = 1e9 + 9;
    
    void Dijkstra(int n, int s) {
        memset(vis + 1, 0, sizeof(vis[0])*n);
        for(int i = 1; i <= n; i++)
            dis[i] = INF;
        priority_queue<Edge_node> pq;
        dis[s] = 0;
        ans[s] = 1;
        pq.push(Edge_node(s, 0));
        while(!pq.empty()) {
            int u = pq.top().v;
            pq.pop();
            if(vis[u])
                continue;
            vis[u] = 1;
            for(int i = head[u]; i; i = edge[i].next) {
                int &v = edge[i].v;
                int &w = edge[i].w;
                if(!vis[v] && dis[v] > dis[u] + w) {
                    dis[v] = dis[u] + w;
                    ans[v] = 1ll * ans[u] * edge[i].k % MOD;
                    pq.push(Edge_node(v, dis[v]));
                } else if(!vis[v] && dis[v] == dis[u] + w) {
                    ans[v] = (ans[v] + 1ll * ans[u] * edge[i].k % MOD) % MOD;
                }
            }
        }
    }
    
    int minw[MAXN];
    int minw2[MAXN];
    int dk[MAXN];
    int dk2[MAXN];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m, q;
        scanf("%d%d%d", &n, &m, &q);
    
        for(int i = 1; i <= m; i++) {
            int d, v, w;
            scanf("%d%d%d", &d, &v, &w);
            if(v == 1) {
                if(minw[d] == 0 || minw[d] > w) {
                    minw[d] = w;
                    dk[d] = 1;
                } else if(minw[d] == w) {
                    ++dk[d];
                }
            } else {
                if(minw2[d] == 0 || minw2[d] > w) {
                    minw2[d] = w;
                    dk2[d] = 1;
                } else if(minw2[d] == w) {
                    ++dk2[d];
                }
            }
        }
        init_graph(n);
        for(int d = 1; d <= n; d++) {
            if(minw[d]) {
                for(int v = 1; v <= n; v += d) {
                    if(v + d <= n) {
                        add_edge(v, v + d, minw[d], dk[d]);
                        add_edge(v + d, v, minw[d], dk[d]);
                    }
                }
            }
        }
        for(int d = 1; d <= n; d++) {
            if(minw2[d]) {
                for(int v = n; v >= 1; v -= d) {
                    if(v - d >= 1) {
                        add_edge(v - d, v, minw2[d], dk2[d]);
                        add_edge(v, v - d, minw2[d], dk2[d]);
                    }
                }
            }
        }
        Dijkstra(n, 1);
        for(int i = 1; i <= q; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            printf("%d
    ", ans[y]);
        }
    }
    

    有点bug,dis应该是ll才对的。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MOD = 1e9 + 9, MAXN = 5e4 + 5, MAXM = 1400000 + 5;
    const ll INF = 1e18;
    struct Edge {
        int v, w, k, next;
        Edge(int v = 0, int w = 0, int k = 0): v(v), w(w), k(k) {}
    };
    
    int h[MAXN], etop;
    Edge e[MAXM];
    
    inline void init_graph(int n) {
        etop = 0;
        memset(h + 1, 0, sizeof(h[0])*n);
    }
    
    inline void add_edge(int u, int v, int w, int k) {
        e[++etop] = Edge(v, w, k);
        e[etop].next = h[u];
        h[u] = etop;
    }
    
    bool vis[MAXN];
    ll dis[MAXN];
    int ans[MAXN];
    priority_queue<pair<ll, int> > pq;
    
    void Dijkstra(int n, int s) {
        //vis pq
        for(int i = 1; i <= n; i++)
            dis[i] = INF;
        dis[s] = 0, ans[s] = 1, pq.push({0, s});
        while(!pq.empty()) {
            int u = pq.top().second;
            pq.pop();
            if(vis[u])
                continue;
            vis[u] = 1;
            for(int i = h[u]; i; i = e[i].next) {
                int &v = e[i].v, &w = e[i].w;
                if(!vis[v] && dis[v] > dis[u] + w) {
                    dis[v] = dis[u] + w;
                    ans[v] = 1ll * ans[u] * e[i].k % MOD;
                    pq.push({-dis[v], v});
                } else if(!vis[v] && dis[v] == dis[u] + w) {
                    ans[v] = (ans[v] + 1ll * ans[u] * e[i].k % MOD) % MOD;
                }
            }
        }
    }
    
    int minw[MAXN], minw2[MAXN], dk[MAXN], dk2[MAXN];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m, q;
        scanf("%d%d%d", &n, &m, &q);
        for(int i = 1; i <= m; i++) {
            int d, v, w;
            scanf("%d%d%d", &d, &v, &w);
            if(v == 1) {
                if(minw[d] == 0 || minw[d] > w) {
                    minw[d] = w;
                    dk[d] = 1;
                } else if(minw[d] == w)
                    ++dk[d];
            } else {
                if(minw2[d] == 0 || minw2[d] > w) {
                    minw2[d] = w;
                    dk2[d] = 1;
                } else if(minw2[d] == w)
                    ++dk2[d];
            }
        }
        init_graph(n);
        for(int d = 1; d <= n; d++) {
            if(minw[d]) {
                for(int v = 1; v <= n; v += d) {
                    if(v + d <= n) {
                        add_edge(v, v + d, minw[d], dk[d]);
                        add_edge(v + d, v, minw[d], dk[d]);
                    }
                }
            }
            if(minw2[d]) {
                for(int v = n; v >= 1; v -= d) {
                    if(v - d >= 1) {
                        add_edge(v - d, v, minw2[d], dk2[d]);
                        add_edge(v, v - d, minw2[d], dk2[d]);
                    }
                }
            }
        }
        Dijkstra(n, 1);
        for(int i = 1; i <= q; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            printf("%d
    ", ans[y]);
        }
    }
    

    来个vector版的比一比。
    感觉差不多,好像vector挺方便的。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MOD = 1e9 + 9, MAXN = 5e4 + 5;
    const ll INF = 1e18;
    
    struct Edge {
        int v, w, k;
        Edge(int v = 0, int w = 0, int k = 0): v(v), w(w), k(k) {}
    };
    
    vector<Edge> e[MAXN];
    inline void add_edge(int u, int v, int w, int k) {
        e[u].emplace_back(v, w, k);
        e[v].emplace_back(u, w, k);
    }
    
    bool vis[MAXN];
    ll dis[MAXN];
    int ans[MAXN];
    priority_queue<pair<ll, int> > pq;
    
    void Dijkstra(int n, int s) {
        //vis pq
        for(int i = 1; i <= n; i++)
            dis[i] = INF;
        dis[s] = 0, ans[s] = 1, pq.push({0, s});
        while(!pq.empty()) {
            int u = pq.top().second;
            pq.pop();
            if(vis[u])
                continue;
            vis[u] = 1;
            for(auto ei : e[u]) {
                int v = ei.v, w = ei.w, k = ei.k;
                if(!vis[v] && dis[v] > dis[u] + w) {
                    dis[v] = dis[u] + w;
                    ans[v] = 1ll * ans[u] * k % MOD;
                    pq.push({-dis[v], v});
                } else if(!vis[v] && dis[v] == dis[u] + w) {
                    ans[v] = (ans[v] + 1ll * ans[u] * k % MOD) % MOD;
                }
            }
        }
    }
    
    int minw[MAXN], minw2[MAXN], dk[MAXN], dk2[MAXN];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m, q;
        scanf("%d%d%d", &n, &m, &q);
        for(int i = 1; i <= m; i++) {
            int d, v, w;
            scanf("%d%d%d", &d, &v, &w);
            if(v == 1) {
                if(minw[d] == 0 || minw[d] > w) {
                    minw[d] = w;
                    dk[d] = 1;
                } else if(minw[d] == w)
                    ++dk[d];
            } else {
                if(minw2[d] == 0 || minw2[d] > w) {
                    minw2[d] = w;
                    dk2[d] = 1;
                } else if(minw2[d] == w)
                    ++dk2[d];
            }
        }
        for(int d = 1; d <= n; d++) {
            if(minw[d])
                for(int v = 1; v + d <= n; v += d)
                    add_edge(v, v + d, minw[d], dk[d]);
            if(minw2[d])
                for(int v = n; v - d >= 1; v -= d)
                    add_edge(v - d, v, minw2[d], dk2[d]);
        }
        Dijkstra(n, 1);
        for(int i = 1; i <= q; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            printf("%d
    ", ans[y]);
        }
    }
    
    
  • 相关阅读:
    Eclipse快捷键大全,导包快捷键:ctrl+Shift+/【转】
    xml合并工具【原】
    解决win10无线无故断网,重启才恢复正常的情况【原】
    PL/SQL可以连oracle,但是jdbc连不上 【转】
    Java 编程下使用 Class.forName() 加载类【转】
    Http请求中Content-Type讲解以及在Spring MVC中的应用【转】
    activeMQ
    概念,包括对象,接口,类,方法
    javabean
    session
  • 原文地址:https://www.cnblogs.com/Yinku/p/11343534.html
Copyright © 2020-2023  润新知