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]);
    }
}

原文地址:https://www.cnblogs.com/Yinku/p/11343534.html