zoukankan      html  css  js  c++  java
  • 多源对多源最短路

    https://ac.nowcoder.com/acm/contest/6116/B
    魔方国有n座城市,编号为1sim n1∼n。城市之间通过n-1条无向道路连接,形成一个树形结构。
    在若干年之后,其中p座城市发展成了大都会,道路的数量也增加到了m条。
    大都会之间经常有贸易往来,因此,对于每座大都会,请你求出它到离它最近的其它大都会的距离。

    蒟蒻第一次见多源对多源最短路,没想到是这种处理方式。

    1. 第一步就是按照正常加一个虚点连接所有的大都会,距离为0然后跑一边dijkstra , 同时记录当前这个点距离哪个大都会最近。
    2. 当前u点最近的大都会from[u] , v点最近的大都会from[v] ,
      如果他们from[u] = from[v] , 那也就是u 和 v两点由同一个点拓展而出 , 否则的话由两个点拓展而出的时候,就可以算一下这两个拓展点之间的最短距离 ,,在这里插入图片描述
      那么其中一个大都会距离另一个大都会的最短距离可更新为ans = min(ans , dis[u] + dis[v] + w )
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <unordered_map>
    #include <vector>
    #include <map>
    #include <list>
    #include <queue>
    #include <cstring>
    #include <cstdlib>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <set>
    #pragma GCC optimize(3 , "Ofast" , "inline")
    using namespace std ;
    #define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
    #define x first
    #define y second
    typedef long long ll ;
    const double esp = 1e-6 , pi = acos(-1) ;
    typedef pair<ll , ll> PII ;
    const int N = 1e6 + 10 , INF = 0x3f3f3f3f , mod = 1e9 + 7;
    ll in()
    {
      ll x = 0 , f = 1 ;
      char ch = getchar() ;
      while(!isdigit(ch)) {if(ch == '-') f = -1 ; ch = getchar() ;}
      while(isdigit(ch)) x = x * 10 + ch - 48 , ch = getchar() ;
      return x * f ;
    }
    int e[N] , ne[N]  , h[N] , n , m , p , idx , a[N]  , vis[N] , from[N] ;
    ll dis[N] , ans[N] , w[N] ;
    void add(int a , int b , int c)
    {
      e[idx] = b , ne[idx] = h[a] , w[idx] = c , h[a] = idx ++ ;
    }
    int main()
    {
      memset(h , -1 , sizeof h) ;
      n = in() , m = in() , p = in() ;
      for(int i = 1; i <= p ;i ++ ) a[i] = in() ;
      for(int i = 1 , a , b , c ; i <= m ;i ++ )
       a = in() , b = in() , c = in() , add(a , b , c) , add(b , a , c) ;
    
      for(int i = 1 ; i <= n ;i ++ ) ans[i] = dis[i] = 1e18 ;
      priority_queue<PII , vector<PII> , greater<PII> > q ;
      for(int i = 1; i <= p ;i ++ )
       q.push({0 , a[i]}) , dis[a[i]] = 0 , from[a[i]] = a[i] ;
      while(q.size())
      {
        auto t = q.top() ;q.pop() ;
        if(vis[t.second]) continue ;
        vis[t.second] = 1 ;
        int u = t.second ;
        for(int i = h[u] ; ~i ; i = ne[i])
         {
           int v = e[i] ;
           if(dis[v] > dis[u] + w[i])
            dis[v] = dis[u] + w[i] , from[v] = from[u] , q.push({dis[v] , v}) ;
           else if(from[v] != from[u])
            {
              ll t = dis[u] + dis[v] + w[i] ;
              ans[from[v]] = min(ans[from[v]] , t) ;
              ans[from[u]] = min(ans[from[u]] , t) ;
            }
         }
      }
      for(int i = 1; i <= p ;i ++ ) cout << ans[a[i]] << " " ;
      puts("") ;
      return 0 ;
    }
    /*
    */
    
    
  • 相关阅读:
    编程之美:位运算应用集萃
    【总结系列】互联网服务端技术体系:高性能之缓存面面观
    【总结系列】互联网服务端技术体系:高性能之并发(Java)
    【总结系列】互联网服务端技术体系:高性能之数据库索引
    【总结系列】互联网服务端技术体系:可扩展之数据分区
    一道关于二叉树的字节面试题的思考
    python基础之range()函数和random模块
    记录下第一次参加leetcode 周赛
    几种方法实现“反转字符串”
    c# 自动更新程序
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/13191577.html
Copyright © 2011-2022 走看看