zoukankan      html  css  js  c++  java
  • P4568 [JLOI2011]飞行路线

    题目描述

    Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 nnn 个城市设有业务,设这些城市分别标记为 000 到 n−1n-1n1 ,一共有 mmm 种航线,每种航线连接两个城市,并且航线有一定的价格。

    Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 kkk 种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

    输入输出格式

    输入格式:

    数据的第一行有三个整数, n,m,kn,m,kn,m,k ,分别表示城市数,航线数和免费乘坐次数。
    第二行有两个整数, s,ts,ts,t ,分别表示他们出行的起点城市编号和终点城市编号。
    接下来有m行,每行三个整数, a,b,ca,b,ca,b,c ,表示存在一种航线,能从城市 aaa 到达城市 bbb ,或从城市 bbb 到达城市 aaa ,价格为 ccc 。

    输出格式:

    只有一行,包含一个整数,为最少花费。

    输入输出样例

    输入样例#1: 
    5 6 1
    0 4
    0 1 5
    1 2 5
    2 3 5
    3 4 5
    2 3 3
    0 2 100
    输出样例#1: 
    8

    说明

    对于30%的数据, 2≤n≤50,1≤m≤300,k=0
    对于50%的数据, 2≤n≤600,1≤m≤6000,0≤k≤1
    对于100%的数据, 2≤n≤10000,1≤m≤50000,0≤k≤10

    Solution:

      本题板子,分层图+最短路。

      对于免费的乘坐机会,等价于使得某条无向边变为0,由于只有10次免费机会,那么最多分10层图,各层的图都对应原图,层数代表着消耗的免费次数,当前层的每条边都可以连有向边指向下一层对应的节点且边权为0,这样去跑最短路,最后只需要统计各层终点的最小值就好了。

    代码:

    /*Code by 520 -- 8.21*/
    #include<bits/stdc++.h>
    #include<ext/pb_ds/assoc_container.hpp>
    #include<ext/pb_ds/priority_queue.hpp>
    #define il inline
    #define ll long long 
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    using namespace __gnu_pbds;
    const int N=3000005,inf=0x7fffffff;
    struct node{
        int u,d;
        bool operator <(const node &a)const {return d>a.d;}
    };
    typedef __gnu_pbds::priority_queue<node,less<node>,pairing_heap_tag> heap;
    heap q;
    heap::point_iterator id[N];
    int n,m,k,s,t,dis[N],ans=inf;
    int to[N],net[N],h[N],w[N],cnt;
    
    int gi(){
        int a=0;char x=getchar();
        while(x<'0'||x>'9')x=getchar();
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return a;
    }
    
    il void add(int u,int v,int c){
        For(i,0,k) {
            to[++cnt]=v+i*n,net[cnt]=h[u+i*n],w[cnt]=c,h[u+i*n]=cnt;
            to[++cnt]=u+i*n,net[cnt]=h[v+i*n],w[cnt]=c,h[v+i*n]=cnt;
            if(i) {
                to[++cnt]=v+i*n,net[cnt]=h[u+(i-1)*n],w[cnt]=0,h[u+(i-1)*n]=cnt;
                to[++cnt]=u+i*n,net[cnt]=h[v+(i-1)*n],w[cnt]=0,h[v+(i-1)*n]=cnt;
            }
        }
    }
    
    il void dij(){
        memset(dis,127,sizeof(dis));
        dis[s]=0,q.push(node({s,0}));
        while(!q.empty()){
            node x=q.top();q.pop();
            for(RE int i=h[x.u];i;i=net[i])
                if(dis[to[i]]>dis[x.u]+w[i]){
                    dis[to[i]]=dis[x.u]+w[i];
                    if(id[to[i]]==0) id[to[i]]=q.push(node({to[i],dis[to[i]]}));
                    else q.modify(id[to[i]],node({to[i],dis[to[i]]}));
                }
        }
    }
    
    il void init(){
        n=gi(),m=gi(),k=gi(),s=gi(),t=gi();
        int u,v,c;
        while(m--) u=gi(),v=gi(),c=gi(),add(u,v,c);
        dij();
        For(i,0,k) ans=min(ans,dis[t+i*n]);
        cout<<ans;
    }
    
    int main(){
        init();
        return 0;
    }
  • 相关阅读:
    【产品设计】设计中的文档管理
    【基础知识】极管类器件的选用
    【Altium Designer】DatabaseLib的使用方法
    【电力电子】功率因素无功功率
    【基础知识】电阻标称阻值查询表
    【元器件】电容的使用
    【EMC】浪涌
    【仪表】电力专用术语
    往mysql中插入一条新的数据
    mysql 中导出表源码
  • 原文地址:https://www.cnblogs.com/five20/p/9515582.html
Copyright © 2011-2022 走看看