zoukankan      html  css  js  c++  java
  • [SRM] 08 C

    C-3 SRM 08

    描述

    给一个图,n 个点 m 条双向边,每条边有其长度。n 个点中有 k 个是特殊点,问任意两个特殊点的最短路是多少。

    输入格式

    第一行三个整数 n m k

    第二行 k 个整数 A_i,为各个特殊点

    接下来 m 行,每行三个整数 x y d,表示 x 到 y 有一条长度为 d 的边

    输出格式

    一个整数

    样例输入

    5 5 3
    1 3 5
    1 2 3
    2 3 4
    3 4 1
    4 5 8
    1 5 19

    样例输出

    7

    数据范围与约定

    • 图为联通图
    • 1 leq A_i,x,y leq n
    • 1 leq d leq 10000
    • 2 leq n leq 100000
    • n-1 leq m leq 300000
    • 2 leq k leq 10000

    样例解释

    样例中,1-3 的最短路为 7,3-5 的最短路为 9,1-5 的最短路为 16,因此答案为最小值 7

    分析

    想象所有的特殊点都在中央,而我们要求的就是:

    那么当那根被称为“最短路”的橡皮筋只捆在特殊点上时,其中的最短的一部分就是我们要求的。

    那么当我们在找最优解的过程就像把这根橡皮筋从无关点上一个点一个点的向特殊点收缩。

    这听起来有些玄幻。

    非常套路地,我们需要求出每个点的最短路(也就是多源最短路),但同时还要记录对应的源点

    这样当我们拎着一条边的时候,如果这条边两端的端点不同,这条边对应的橡皮筋的部分长度为 A点的最短路+边长+B点最短路。

    这样我们可以在求最短路的过程中顺便求解。

    代码

     1 #include<cstdio>
     2 #include<queue>
     3 #include<iostream>
     4 #define maxn_E 5050500
     5 #define maxn_P 1010100
     6 #define INF 2147483647
     7 using namespace std;
     8 typedef pair<int,int> node;
     9 priority_queue<node,vector<node>,greater<node> > q;
    10 
    11 struct edge{
    12     int from,v,len;
    13 }e[maxn_E];
    14 
    15 int first[maxn_P],tot,ans = INF,n,m,k,a,b,c,dis[maxn_P],sou[maxn_P],spe[maxn_P];
    16 bool book[maxn_P];
    17 
    18 void insert(int u,int v,int len){
    19     tot++;
    20     e[tot].from = first[u];
    21     e[tot].v = v;
    22     e[tot].len = len;
    23     first[u] = tot;
    24 }
    25 
    26 void dijkstra(){
    27     for(int i = 1;i <= n;i++) dis[i] = INF;
    28     for(int i = 1;i <= k;i++){
    29         q.push(make_pair(0,spe[i]));
    30         dis[spe[i]] = 0;
    31         sou[spe[i]] = spe[i];
    32     } 
    33     
    34     while(!q.empty()){
    35         node tmp = q.top();
    36         q.pop();
    37         
    38         int p = tmp.second;
    39         
    40         if(!book[p]){
    41             book[p] = true;
    42             for(int i = first[p];i;i = e[i].from){
    43                 if(dis[p] != INF && dis[e[i].v] != INF && sou[p] != sou[e[i].v])
    44                         ans = min(ans,dis[p]+e[i].len+dis[e[i].v]);
    45                 if(dis[e[i].v] > dis[p]+e[i].len && !book[e[i].v]){
    46                     if(sou[e[i].v] != sou[p])
    47                         sou[e[i].v] = sou[p];
    48                     dis[e[i].v] = dis[p]+e[i].len;
    49                     q.push(make_pair(dis[e[i].v],e[i].v));
    50 //                    if(sou[p] != sou[e[i].v])
    51 //                        ans = min(ans,dis[p]+e[i].len+dis[e[i].v]);
    52                 }
    53             }
    54         }
    55     }
    56 }
    57 
    58 int main(){
    59     scanf("%d%d%d",&n,&m,&k);
    60     
    61     for(int i = 1;i <= k;i++) scanf("%d",&spe[i]);
    62     
    63     for(int i = 1;i <= m;i++){
    64         scanf("%d%d%d",&a,&b,&c);
    65         insert(a,b,c);
    66         insert(b,a,c);
    67     }
    68     
    69     dijkstra();
    70     
    71 //    for(int i = 1;i <= n;i++){
    72 //        printf("%d/%d ",dis[i],sou[i]);
    73 //    }
    74     
    75     printf("%d",ans);
    76     
    77     return 0;
    78 } 
    推荐不看
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    java 之 对象与垃圾回收
    Java 之 内部类
    java 接口(interface)
    抽象类
    Java之fianl修饰符
    类的继承
    上传图片
    一般处理程序 给图片添加文字水印
    socket
    初识linq,lambda表达式
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7257260.html
Copyright © 2011-2022 走看看