• 最短路计数(SPFA× Dijkstra√)


    题目描述

    给出一个N个顶点M条边的无向无权图,顶点编号为1N。问从顶点1开始,到其他每个点的最短路有几条。

    输入格式

    第一行包含2个正整数N,M,为图的顶点数与边数。

    接下来M行,每行2个正整数x,y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。

    输出格式

    N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans mod 100003后的结果即可。如果无法到达顶点i则输出0。


    一道简单题, 用SPFA去更新最短路, 每次更新时, 即dis[y] > dis[x] + v, 点y的最短路条数就等于点x的最短路条数, 而当dis[y] = dis[x] + v时, 就说明该点产生了第二条最短路, 即点y最短路的条数加上点x最短路的条数。 即使当前不是最短路, 但是当更新到最短路时, 该最短路条数数组会重置成此时点x的最短路条数, 所以这个算法是正确的。

    (补更~) 虽然SPFA过了边权为1的数据, 但今天机房某位大佬出了一个边权不为1的数据, 卡掉了SPFA, 然后我就知道要用Dijkstra算法, 具体SPFA算法为什么被卡我也不是很知道。

    被卡数据如下 :

    4 4
    1 2 2
    2 3 1
    1 3 3
    3 4 1

    代码已更新:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 2e6 + 100;
    const int MAXM = 3e3 + 10;
    
    template < typename T > inline void read(T &x) {
        x = 0; T ff = 1, ch = getchar();
        while(!isdigit(ch)) {
            if(ch == '-') ff = -1;
            ch = getchar();
        }
        while(isdigit(ch)) {
            x = (x << 1) + (x << 3) + (ch ^ 48);
            ch = getchar();
        }
        x *=ff;
    }
    
    template < typename T > inline void write(T x) {
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) write(x / 10);
        putchar(x % 10 + '0');
    }
     
    int n, m;
    int dis[MAXN], vis[MAXN], a[MAXN]; 
    int lin[MAXN], tot = 0;
    struct edge {
        int y, v, next;
    }e[MAXN];
    
    inline void add(int xx, int yy, int vv) {
        e[++tot].y = yy;
        e[tot].v = vv;
        e[tot].next = lin[xx];
        lin[xx] = tot;
    }
    
    /*inline void SPFA() {
        memset(dis, 0x3f, sizeof(dis));
        memset(vis, false, sizeof(vis));
        queue < int > q; 
        dis[1] = 0; a[1] = 1;
        q.push(1);
        while(!q.empty()) {
            int x = q.front(); q.pop();
            vis[x] = false;
            for(int i = lin[x], y; i; i = e[i].next) {
                if(dis[y = e[i].y] > dis[x] + 1) {
                    dis[y] = dis[x] + 1;
                    a[y] = a[x]; 
                    if(!vis[y]) {
                        vis[y] = true;
                        q.push(y);
                    }
                }
                else if(dis[y] == dis[x] + 1) {
                    a[y] += a[x];
                    a[y] %= 100003;
                }
            }
        }
    }*/
    
    inline void Dijkstra() {
        memset(dis, 0x3f, sizeof(dis));
        memset(vis, false, sizeof(vis));
        priority_queue < pair < int, int > > q;
        q.push(make_pair(0, 1));
        dis[1] = 0;
        a[1] = 1;
        while(!q.empty()) {
            int x = q.top().second;
            q.pop();
            if(vis[x]) continue;
            for(int i = lin[x], y; i; i = e[i].next) {
                if(dis[y = e[i].y] == dis[x] + e[i].v) a[y] = (a[y] + a[x]) % 100003;
                else if(dis[y] > dis[x] + e[i].v) {
                    a[y] = a[x];
                    dis[y] = dis[x] + e[i].v;
                    q.push(make_pair(-dis[y], y));
                }
            }
        }
    }
    
    int main() {
        read(n); read(m);
        for(int i = 1; i <= m; ++i) {
            int u, v;
            read(u); read(v);
            if(u == v) continue;
            add(u, v, 1);
            add(v, u, 1);
        }
        Dijkstra();
        for(int i = 1; i <= n; ++i) {
            write(a[i]);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    datatables出现横向滚动条
    mumu模拟器设置代理/打开网络连接(windows)
    a标签下划线
    python 配置导入方式
    redis命令
    django+mongodb 内置用户控制
    异常补充
    关于异常的总结
    java 常用类的方法
    java 日期时间类加Calendar的set和add方法
  • 原文地址:https://www.cnblogs.com/AK-ls/p/11423504.html
Copyright © 2020-2023  润新知