zoukankan      html  css  js  c++  java
  • 最短路径并查集+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的幂会很大,你要怎么去处理?

  • 相关阅读:
    浅谈通信网络(五)——TCP层
    浅谈通信网络(四)——报文转发(IP/MAC)
    浅谈通信网络(三)——TCP/IP协议
    《linux内核设计与实现》阅读笔记-进程与调度
    深入理解计算机系统 BombLab 实验报告
    汇编语言十二
    汇编语言十一
    汇编语言实验十
    汇编语言实验九
    汇编语言实验七
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/9230732.html
Copyright © 2011-2022 走看看