洛谷 P1608 路径统计 【膜改dij】

传送门
// 题意: 就是求1-n的最短路条数.

注意一个点就是重边只算一条(所以我wa了两发), 所以我们建图时需要去重.

然后开一个数组记录下到这个点时最短路有多少条, 所以当dis[to] == dis[u.to] + e[i].w; 就要更新这个记录数组, ans[to] += ans[u.to];
就是在原先的dij进行一些小的改变即可.
AC Code

const int maxn = 2e3+5;
int cas=1;
struct node {
    int to, next, w;
    bool operator <(const node & a) const {
        return w > a.w;
    }
}e[maxn*maxn];
int cnt, head[maxn];
void add(int u, int v, int w) {
    e[cnt] = node{v, head[u], w};
    head[u] = cnt++;
}
void init() {
    cnt = 0;
    Fill(head, -1);
}
int dis[maxn], vis[maxn];
int ans[maxn];
void dij(int st, int ed) {
    priority_queueq;
    q.push(node{st, 0, 0});
    Fill(dis, inf); Fill(vis, 0); Fill(ans ,0);
    dis[st] = 0; ans[st] = 1;
    while(!q.empty()) {
        node u = q.top();
        q.pop();

        if (vis[u.to]) continue;
        vis[u.to] = 1;

        for (int i = head[u.to] ; ~i ; i = e[i].next) {
            int to = e[i].to;
            int d = u.w + e[i].w;
           // cout << "BBB" <<  u.to << ' ' << to << ' ' << dis[to] << ' ' << d << ' ' << endl;
            if (d < dis[to]) {
                dis[to] = d;
                ans[to] = ans[u.to];
                q.push(node{to, 0, d});
            }
            else if (d == dis[to]) ans[to] += ans[u.to];
           // cout << "AAA" << ans[u.to] << ' ' << ans[to] << endl;
        }
    }
    if (dis[ed] == inf) cout << "No answer" << endl;
    else printf("%d %d\n", dis[ed], ans[ed]);
}
int s[maxn][maxn];
void solve()
{
    int n, m;
    scanf("%d%d",&n, &m);
    init();
    for (int i = 1 ; i <= m ; i ++) {
        int u, v, w;
        scanf("%d%d%d ", &u, &v, &w);
        if (s[u][v] == w) continue;  // 去重
        s[u][v] = w;
        add(u, v, w);
    }
    dij(1, n);
}

你可能感兴趣的:(最短路相关)