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;
}
原文地址:https://www.cnblogs.com/five20/p/9515582.html