最短路径-并查集+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
输出
复制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的幂会很大,你要怎么去处理?