1. 程式人生 > >[JLOI2011]飛行路線(分層圖)

[JLOI2011]飛行路線(分層圖)

技術 一行 lin size 價格 namespace 現在 mage ima

[JLOI2011]飛行路線

題目描述

Alice和Bob現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在 n 個城市設有業務,設這些城市分別標記為 0 到 n?1 ,一共有 m 種航線,每種航線連接兩個城市,並且航線有一定的價格。

Alice和Bob現在要從一個城市沿著航線到達另一個城市,途中可以進行轉機。航空公司對他們這次旅行也推出優惠,他們可以免費在最多 k 種航線上搭乘飛機。那麽Alice和Bob這次出行最少花費多少?

輸入輸出格式

輸入格式:

數據的第一行有三個整數, n,m,k ,分別表示城市數,航線數和免費乘坐次數。
第二行有兩個整數, s,t ,分別表示他們出行的起點城市編號和終點城市編號。

接下來有m行,每行三個整數, a,b,c ,表示存在一種航線,能從城市 a 到達城市 b ,或從城市 b 到達城市 a ,價格為 c 。

輸出格式:

只有一行,包含一個整數,為最少花費。

輸入輸出樣例

輸入樣例#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 \le n \le 50,1 \le m \le 300, k =0\)
對於50%的數據, \(2\le n \le 600,1 \le m \le 6000, k \le 1\)
對於100%的數據, \(2\le n \le 10000,1 \le m \le 50000,0 \le k \le 10 \le s,t<n,0 \le a,b<n,a\neq b,0 \le c \le 1000\)



題解

分層圖的模板題吧。
可以說模板到不能再模板了,比那個集訓隊論文的題目還要簡單。

技術分享圖片

從洛谷偷一張圖更直觀。
免費的路徑就直接接到下一層圖吧,然後是不需要消費的。
同一層的路徑該消費的還是要消費的,因為只有k層,所以一定不會超出限制哦~.


代碼

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e6+5;
struct node{
    int nex,to,v;
}e[N<<2];
int dis[N],vis[N];
int n,m,k,num,head[N];
int s,t;
priority_queue<pair<int,int> >q;
int read(){
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}

void add(int from,int to,int v){
    num++;
    e[num].to=to;
    e[num].v=v;
    e[num].nex=head[from];
    head[from]=num;
}

void dijkstra(){
    memset(dis,63,sizeof(dis));dis[s]=0;
    q.push(make_pair(dis[s],s));
    while(q.size()){
        int u=q.top().second;q.pop();if(vis[u])continue;vis[u]=1;
        for(int i=head[u];i;i=e[i].nex){
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].v){
                dis[v]=dis[u]+e[i].v;
                q.push(make_pair(-dis[v],v));
            }
        }
    }
}

int main(){
    n=read();m=read();k=read();
    if(k>=m){printf("0");return 0;}
    s=read();t=read();t=n*k+t;
    for(int i=1;i<=m;i++){
        int x=read(),y=read(),z=read();
        add(x,y,z);add(y,x,z);
        for(int j=1;j<=k;j++){
            add(x+(j-1)*n,y+j*n,0);
            add(y+(j-1)*n,x+j*n,0);
            add(x+j*n,y+j*n,z);
            add(y+j*n,x+j*n,z);
        }
    }
    dijkstra();
    printf("%d",dis[t]);
    return 0;
}

[JLOI2011]飛行路線(分層圖)