zoukankan      html  css  js  c++  java
  • 校内测T2 李白坐地铁(Dijkstra模板题)

    题目背景

    济南地铁已经开通了R1和R3线。

    小李白也兴奋地在高考前去体验了一下,发现可以用公交卡刷卡并且车站文化氛围很浓厚qwqqwq

    题目描述

    小李白来到了一个大城市,他住在了一个五星级酒店,他规划着接下来的几天内在大城市的城区内坐地铁游玩景点。这个城市有着完善的地铁网络。但是非常不幸的是,地铁全是单向行驶的。

    小李白每天都要坐地铁去一个景点游玩,然后傍晚时分坐地铁回来。第一天去编号为2的景点,第二天去编号为3的景点......小李白要去过所有的景点才会罢休qwqqwq。我们设每一个地铁站点都是一个景点。对于每一天的景点,小李白都想知道如何坐地铁才能使得来回总时间合最小。他会给你整个城市的地铁路线和站点图,并且向你求助这个问题。

    nn个站点,mm个站点间的地铁线路。小李白所住的酒店需要耗时时间dd才能到地铁站11,也就是从站点11开始坐地铁。

    数据会给你每对站点之间的路线长度ww.

    输入格式

    第1行:n,m,dn,m,d

    2到m+12m+1行,u,v,w,表示从站点u到站点v有一条长度为w的地铁路线。

    输出格式

    小李白每天在路上耗时的和sumsum。 为了更方便的解释,我们设每天在路上花费的时间为time[i]time[i],小李白要去的景点数为kk

    那么答案就是sum_{i=1}^k time[i]i=1ktime[i]

    输入输出样例

    输入 #1
    5 10 0
    2 3 5
    1 5 5
    3 5 6
    1 2 8
    1 3 8
    5 3 4
    4 1 8
    4 5 3
    3 5 6
    5 4 2
    输出 #1
    83

    说明/提示

    对于30\%30%的数据,n=1n=1

    对于100\%100%的数据:

    nleqslant1000n1000

    mleqslant100000m100000

    wleqslant200w200

    dleqslant1500000d1500000

    均为整数。

    小李白远远不如他的朋友ych强,所以只能结合高考前放假经历随便出了个题

    注意空间时间限制qwqqwq

    qwq_{ych_{Orz}}^{ybr_{csl}^{tcl}}

    思路:

    参观每一个景点都要从一号车站过去再回来,所以很明显是一个单源最短路,因为没有负边权,所以可以使用比SPFA更快的Dijkstra算法来求单源最短路。但是从各个景点回来的时候应该怎么办呢?通过dalao的题解,我学会了建反边这一个神奇的操作。因为每次从景点回来都是回到一号车站,都是那一个点,所以如果在另一张新图里反向建边,就可以再跑一遍Dijkstra,从而转化为单源最短路(妙啊)

     
    代码:
     
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    using namespace std;
    const int N=1005,M=100005;
    long long n,m,k,tot1,tot2,ans;
    long long Next1[M],ver1[M],edge1[M],head1[N],d1[N],Next2[M],ver2[M],edge2[M],head2[N],d2[N];//不开longlong见祖宗 
    bool v1[N],v2[N];
    priority_queue< pair <int,int> >q1;
    priority_queue< pair <int,int> >q2;//因为要存两个图,所以什么变量都开两遍 
    void add1(long x,long long y,long long z){
        ver1[++tot1]=y;//编号为tot的边的终点是y 
        edge1[tot1]=z;//边权是z 
        Next1[tot1]=head1[x];//新加入的边的下一条边是原本与x相连的第一条边     
        head1[x]=tot1;//链式前向星结构,把新加入的边放到与x相连接的第一条边
    }
    void add2(long long x,long long y,long long z){
        ver2[++tot2]=y;
        edge2[tot2]=z;
        Next2[tot2]=head2[x];
        head2[x]=tot2;
    }
    void dijkstra1(long long x){
        memset(d1,0x3f,sizeof(d1));//把起点到所有点的距离都初始化为无穷大,保证能更新 
        memset(v1,0,sizeof(v1));//一开始所有点都没有到过 
        d1[x]=0;//自己到自己的距离当然是0 
        q1.push(make_pair(0,x));//pair的第一维表示点x到起点的距离,第二维表示点的编号x 
        while(q1.size()!=0){//当堆不为空 
            long long x=q1.top().second;//取出第二维点的编号 
            q1.pop();//弹出 
            if(v1[x]==1) continue;//如果这个点已经被访问过了,那么继续循环 
            v1[x]=1;//如果没有访问过那么标记为访问过 
            for(long long i=head1[x];i;i=Next1[i]){//链式前向星遍历
                long long y=ver1[i],z=edge1[i];
                if(d1[y]>d1[x]+z){//松弛操作 
                    d1[y]=d1[x]+z;
                    q1.push(make_pair(-d1[y],y));//加入堆中,因为STL中提供的是大根堆,我们要用小根堆,所以把距离的相反数存进去排序,就相当于是小根堆了 
                }
            }
        }
    }
    void dijkstra2(long long x){
        memset(d2,0x3f,sizeof(d2));
        memset(v2,0,sizeof(v2));
        d2[x]=0;
        q2.push(make_pair(0,x));
        while(q2.size()!=0){
            long long x=q2.top().second;
            q2.pop();
            if(v2[x]==1) continue;
            v2[x]=1;
            for(long long i=head2[x];i;i=Next2[i]){ 
                long long y=ver2[i],z=edge2[i];
                if(d2[y]>d2[x]+z){
                    d2[y]=d2[x]+z;
                    q2.push(make_pair(-d2[y],y));
                }
            }
        }
    }
    int main()
    {
        scanf("%lld%lld%lld",&n,&m,&k);
        for(long long i=1,x,y,z;i<=m;i++){
            scanf("%lld%lld%lld",&x,&y,&z);
            add1(x,y,z);
            add2(y,x,z);//反着建边 
        }
         ans=(n-1)*k*2;//每天从酒店到一号车站所要走的距离 
        dijkstra1(1);
        dijkstra2(1);//跑两遍Dijkstra 
        for(long long i=1;i<=n;i++){
            ans+=d1[i]+d2[i];//把来回的距离和加起来 
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    linux_grep操作
    linux_awk操作
    linux_sed操作
    [题解]USACO 5.2.1 Snail Trails
    [数据生成器]UVA10054 The Necklace
    [题解]UVA10054 The Necklace
    [题解]UVA11027 Palindromic Permutation
    [题解]UVA10129 Play on Words
    [题解]UVA11029 Leading and Trailing
    计蒜客NOIP2017提高组模拟赛(五)day1-机智的 AmyZhi
  • 原文地址:https://www.cnblogs.com/57xmz/p/13288470.html
Copyright © 2011-2022 走看看