zoukankan      html  css  js  c++  java
  • 洛谷 P1342 请柬 最短路+Dijkstra算法

    题面

    题目链接

    P1342 请柬

    题目描述

    在电视时代,没有多少人观看戏剧表演。Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片。他们已经打印请帖和所有必要的信息和计划。许多学生被雇来分发这些请柬。每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与。

    这里的公交系统是非常特殊的:所有的线路都是单向的,连接两个站点。公共汽车离开起始点,到达目的地之后又空车返回起始点。学生每天早上从总部出发,乘公交车到一个预定的站点邀请乘客。每个站点都被安排了一名学生。在一天结束的时候,所有的学生都回到总部。现在需要知道的是,学生所需的公交费用的总和最小是多少。

    输入输出格式

    输入格式

    第1行有两个整数n、m(1<=n,m<=1000000),n是站点的个数,m是线路的个数。

    然后有m行,每行描述一个线路,包括3个整数,起始点,目的地和价格。

    总部在第1个站点,价钱都是整数,且小于1000000000。

    输出格式

    输出一行,表示最小费用。

    输入输出样例

    输入样例

    4 6
    1 2 10
    2 1 60
    1 3 20
    3 4 10
    2 4 5
    4 1 50
    

    输出样例

    210
    

    说明

    【时空限制】

    1000ms,128M

    思路

    其实这一题就是求1到所有点最短路之和所有点到1的最短路之和的和(因为是有向边,所以这当然是不相等的啦)

    前面一项好求,就是单源最短路径。后面一项可以稍微变化一下,我们可以把边反着建,即把u和v对调,再跑从1开始的单源最短路径,这就是所有点到1的最短路的之和了

    AC代码

    #include<bits/stdc++.h>
    const int maxn=1000010;
    using namespace std;
    
    int n,m,tot;
    int t1[maxn],n1[maxn],h1[maxn],len[maxn];
    int t2[maxn],n2[maxn],h2[maxn];
    long long d1[maxn],d2[maxn],ans;
    bool b1[maxn],b2[maxn];
    priority_queue< pair<long long,int> > q1,q2;
    
    void dijkstra1()
    {
        q1.push(make_pair(0,1));
        while(!q1.empty())
        {
            int u=q1.top().second;q1.pop();
            if(b1[u]) continue;
            b1[u]=true;
            for(int i=h1[u];i;i=n1[i])
            {
                int v=t1[i];
                if(d1[v]>d1[u]+len[i])
                {
                    d1[v]=d1[u]+len[i];
                    q1.push(make_pair(-d1[v],v));
                }
            }
        }
        for(int i=2;i<=n;i++) ans+=d1[i];
    }
    
    void dijkstra2()
    {
        q2.push(make_pair(0,1));
        while(!q2.empty())
        {
            int u=q2.top().second;q2.pop();
            if(b2[u]) continue;
            b2[u]=true;
            for(int i=h2[u];i;i=n2[i])
            {
                int v=t2[i];
                if(d2[v]>d2[u]+len[i])
                {
                    d2[v]=d2[u]+len[i];
                    q2.push(make_pair(-d2[v],v));
                }
            }
        }
        for(int i=2;i<=n;i++) ans+=d2[i];
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int u,v,w;scanf("%d%d%d",&u,&v,&w);
            t1[i]=v;n1[i]=h1[u];h1[u]=i;len[i]=w;
            t2[i]=u;n2[i]=h2[v];h2[v]=i;
        }
        for(int i=2;i<=n;i++) d1[i]=d2[i]=LLONG_MAX/2;
        dijkstra1();
        dijkstra2();
        printf("%lld",ans);
        return 0;
    }
    

    总结

    反向建边经常用到,灵性啊

  • 相关阅读:
    工资到帐的快乐排名第四
    如何成为一个具有批判性思维的人?
    别让千里马被驴踢死
    接口协议抓包与分析
    Qt + ffmpeg+SDl (转)
    各种流媒体服务器的架设(二)
    memcpy(转)
    java之public class和class声明区别详解 (转)
    cin、cin.get()、cin.getline()、getline()、gets()等函数的用法 (转)
    const_iterator 与 const iterator
  • 原文地址:https://www.cnblogs.com/Mercury04/p/9754968.html
Copyright © 2011-2022 走看看