最短路径并查集+Floyd[转载]

题目描述

N个城市,标号从0到N-1,M条道路,第K条道路(K从0开始)的长度为2^K,求编号为0的城市到其他城市的最短距离

输入描述:

第一行两个正整数N(2<=N<=100)M(M<=500),表示有N个城市,M条道路
接下来M行两个整数,表示相连的两个城市的编号

输出描述:

N-1行,表示0号城市到其他城市的最短路,如果无法到达,输出-1,数值太大的以MOD 100000 的结果输出。
示例1

输入

复制
4 4
1 2
2 3
1 3
0 1

输出

复制
8
9
11

https://www.cnblogs.com/lca1826/p/6748372.html 关于快速幂的讲解
https://www.cnblogs.com/Asimple/p/6502632.html 代码来自于这个
//Asimple
//#include <bits/stdc++.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cctype>
#include <cstdlib>
#include <stack>
#include <cmath>
#include <set>
#include <map>
#include <string>
#include <queue>
#include <limits.h>
#include <time.h>
#define INF 0xfffffff
#define mod 100000
#define PI 3.14159265358979323
#define swap(a,b,t) t = a, a = b, b = t
#define CLS(a, v) memset(a, v, sizeof(a))
#define debug(a)  cout << #a << " = "  << a <<endl
#define dobug(a, b)  cout << #a << " = "  << a << " " << #b << " = " << b << endl
using namespace std;
typedef long long ll;
const int maxn = 101;
int n, m, num, T, k, len, ans, sum, x, y;
int Map[maxn][maxn];
int fa[maxn];
ll qpow(ll a, ll b, ll md) {//这里使用快速幂来计算2的k次方,并且每次都%md,保证不溢出
    ll ans = 1;
    while( b ) {
        if( b & 1 ) ans = ans * a % md;
        a = a * a % md;
        b = b >> 1;
    }
    return ans;
}
int find(int x) {
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
 
void solve() {
    x = find(0);
    for(int i=1; i<n; i++) {
        if( x!=find(i) ) cout << "-1" << endl;//如果不在一个集合里,那么就-1
        else cout << Map[0][i] << endl;
    }
}
 
void input() {
    while( cin >> n >> m ) {
        for(int i=0; i<n; i++) {
            fa[i] = i;
            Map[i][i] = 0;
        }
        for(int i=0; i<m; i++) {
            cin >> x >> y;
            num = qpow(2, i, mod);
            int xx = find(x);
            int xy = find(y);
            if( xx==xy ) continue;//如果已经联通了,那么就忽略,因为后来的边权值一定比原来的所有边大,已经联通就不用再放进来了。
            for(int j=0; j<n; j++) {
                if( xx!=find(j) ) continue;//也就是找到当前集合的根
                for(int k=0; k<n; k++) {
                    if( xy!=find(k) ) continue;
                    Map[j][k] = Map[k][j] = (Map[j][x] + num + Map[y][k])%mod;
                }
            }
            fa[xy] = xx;
        }
        solve();
    }
}
 
int main(){
    input();
    return 0;
}

//学习到了很多,b&1得到的结果只是个位与。==我觉得难点就在于这个2的幂会很大,你要怎么去处理?

原文地址:https://www.cnblogs.com/BlueBlueSea/p/9230732.html