• 赛艇表演 51nod提高组模拟试题


    AC通道

    题目描述

    小明去某个地区观看赛艇比赛,这个地区共有n个城市和m条道路,每个城市都有赛艇比赛,在第i个 城市观看赛艇表演的价钱为ai, 去其他城市观看也需要支付赛艇表演的价格。任意两个城市之间通过 一条公路连接,并且道路是双向通行的, 观看赛艇比赛时经过的每一条道路都要支付一定的过路费, 观看完比赛返回家时经过的每一条道路也要支付过路费。 对于每个城市u,你需要为小明确定一个城市v,使得从u出发,前往v看赛艇表演,再从v回到u,u可 以等于v,要求花费的总金额尽量的少。请根据题目给出的数据输出总金额。

    输入格式

    第一行两个正整数n和m。 接下来m行,每行三个正整数u,v,w,表示有一条双向道路连接u和v,且每经过一次的过路费是 w。 接下来一行n个数,第i个数表示在第i个城市观看赛艇表演的价钱。

    输出格式

    输出一行n个数,第i个数表示从第i个城市出发至少要花多少钱

    数据范围

    对于前30%的数据,n<=10,m<=20。 对于前50%的数据,n<=100,m<=500。 对于前70%的数据,n<=1500,m<=2000。 对于前85%的数据,图的结构以某种方式随机生成。 对于100%的数据,n<=2e5,m<=2e5,过路费和门票钱都在[1,1e12]内。

    输入样例

    4 2

    1 2 4

    2 3 7

    6 20 1 25

    输出样例

    6 14 1 25

    一道十分有趣的题。首先的思路肯定是对于每个城市,枚举终点,并求出其对应的最短路。

    然而,毫无疑问,这样的结果便是一片TLE。

    这道题最棘手的一点,便是每个点本身的price 和 路径的w均会对结果造成影响。

    而这也导致我们不能直接使用最短路算法求出路径w最小。

    考虑一种方法,使得price和w可以同时被考虑。

    而且原题已经明确的给出了我们一张图,也要尽量利用这张图。

    想出一种建图方法:

    设立一个超级源点S,将其和所有的点之间连边,大小为price,然后从其跑最短路。最短路得到的dis即为每个点的答案。

    而点与点之间的路径,完全可以直接设为2w,不用真的跑来回。这样,我们就直接考虑了price和w。

    可以看一下对应操作: 对于下图三号点,从s直接到3即为在原地观看,从s -> 1 -> 3即为从3点去1点观看。

    (惊叹,斜视,默坐,以为绝妙)

    千少万少,代码不能少

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100010
    #define ll long long
    
    inline ll read(){
        ll x = 0, s = 1;
        char c = getchar();
        while(!isdigit(c)){
            if(c == '-')s = -1;
            c = getchar();
        }
        while(isdigit(c)){
            x = (x << 1) + (x << 3) + (c ^ '0');
            c = getchar();
        }
        return x * s;
    }
    
    ll n, m;
    struct hehe{
        ll u, v, w;
        ll next;
    }t[N];
    ll f[N];
    
    struct node{
        ll now, dis;
        bool operator < (const node& a) const{
            return dis > a.dis;
        }
    };
    
    ll d[N];
    bool vis[N];
    priority_queue <node> q;
    
    ll bian = 0;
    inline void add(ll u, ll v, ll w){
        t[++bian].u = u;
        t[bian].v = v;
        t[bian].w = w;
        t[bian].next = f[u];
        f[u] = bian;
        return ;
    }
    
    void dijstra(ll s){
        memset(d, 127, sizeof(d));
        q.push((node){s,0});
        d[s] = 0;
        while(!q.empty()){
            node temp = q.top();
            q.pop();
            ll now = temp.now, dis = temp.dis;
            if(!vis[now]){
                vis[now] = 1;
                for(int i = f[now];i;i = t[i].next){
                ll v = t[i].v, w = t[i].w, u = t[i].u;
                    if(d[v] > d[u] + w){
                        d[v] = d[u] + w;
                        if(!vis[v]) q.push((node) {v, d[v]});
                    }
                }
            }
        }
        return ;
    }
    
    int main(){
        n = read(), m = read();
        for(int i = 1;i <= m; i++){
            ll x = read(), y = read(), w = read();
            add(x, y, w << 1);add(y, x, w << 1);
        }
        for(int i = 1;i <= n; i++){
            ll x = read();
            add(0, i, x);
            add(i, 0, x);
        }
        dijstra(0);
        for(int i = 1;i <= n; i++)
            printf("%d ",d[i]);
        return 0;
    }

     

  • 相关阅读:
    centos7安装kafka
    Qt——透明无边框Widget的bug
    Qt——浅谈样式表
    Qt——QLineEdit使用总结
    Qt——信号槽连接:基于字符串与基于函数的连接之间的不同
    Qt——树的搜索实现源码
    Qt——树结点的搜索
    Qt——鼠标拖动调整窗口大小
    Qt——右键菜单
    Qt——正则表达式
  • 原文地址:https://www.cnblogs.com/wondering-world/p/12757302.html
Copyright © 2020-2023  润新知