【图论之多源最短路】多源最短路专题(弗洛伊德算法)

注:弗洛伊德算法也可以在数据范围很小时(\(10^2\)级别)求单源最短路,例如3488.最短路径。优点是弗洛伊德算法相对于Dijkstra更好写,就三个for循环,代码比较短,缺点是只有在数据范围是\(10^2\)级别才能用。

3488. 最短路径

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 110, MOD = 100000, INF = 0x3f3f3f3f;

int n, m;
int p[N];
int d[N][N];

int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++ ) p[i] = i;
    
    memset(d, 0x3f, sizeof d);
    for(int i = 0; i < n; i ++ ) d[i][i] = 0;
    
    for(int i = 0, len = 1; i < m; i ++, len = len * 2 % MOD)
    {
        int a, b;
        cin >> a >> b;
        if(find(a) != find(b))
        {
            p[find(a)] = find(b);
            d[a][b] = d[b][a] = len;
        }
    }
    
    for(int k = 0; k < n; k ++ )
        for(int i = 0; i < n; i ++ )
            for(int j = 0; j < n; j ++ )
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
                
    for(int i = 1; i < n; i ++ )
        if(d[0][i] == INF) puts("-1");
        else cout << d[0][i] % MOD << endl;
        
    return 0;
}

附堆优化Dijkstra解法

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 110, M = 500 * 2 + 10, mod = 100000;

int n, m, id;
int h[N], e[M], ne[M], w[M], idx;
int dist[N];
int p[N];
bool st[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

LL qmi(LL a, int k)
{
    LL res = 1;
    while (k)
    {
        if (k & 1) res = res * a % mod;
        k >>= 1;
        a = a * a % mod;
    }
    return res;
}

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[0] = 0;  // 点的标号从0开始
    
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 0}); // 第二位是点的编号,第一位是距离
    
    while (heap.size())
    {
        PII t = heap.top();
        heap.pop();
        
        int ver = t.second, distance = t.first;
        if (st[ver]) continue;
        st[ver] = true;
        
        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > distance + w[i])
            {
                dist[j] = distance + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    
}

int main()
{
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    for (int i = 0; i < n; i ++ ) p[i] = i;
    while (m -- )
    {
        int a, b;
        scanf("%d%d", &a, &b);
        int c = qmi(2, id);
        id ++ ;
        if (find(a) != find(b))
        {
            p[find(a)] = find(b);
            add(a, b, c);
            add(b, a, c);
        }
    }
    dijkstra();
    for (int i = 1; i < n; i ++ )
    {
        if (dist[i] == 0x3f3f3f3f) puts("-1");
        else printf("%d\n", dist[i] % mod);
    }
    return 0;
}
posted @ 2023-04-12 17:40  Tshaxz  阅读(19)  评论(0编辑  收藏  举报
Language: HTML