1. 程式人生 > >Luogu P4568 [JLOI2011]飛行路線【題解】(分層圖最短路模板)

Luogu P4568 [JLOI2011]飛行路線【題解】(分層圖最短路模板)

題目描述

A l i c e Alice B o

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

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

輸入輸出格式

輸入格式:

資料的第一行有三個整數, n n m m k k ,分別表示城市數,航線數和免費乘坐次數。
第二行有兩個整數, s s t t ,分別表示他們出行的起點城市編號和終點城市編號。
接下來有m行,每行三個整數, a a b b c c ,表示存在一種航線,能從城市 a a 到達城市 b b ,或從城市 b b 到達城市 a a ,價格為 c 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 n 50 2 \le n \le 50 , 1 m 300 1 \le m \le 300 , k = 0 k=0 ,
對於50%的資料, 2 n 600 2 \le n \le 600 , 1 m 6000 1 \le m \le 6000 , 0 k 1 0\le k \le 1 ;
對於100%的資料, 2 n 10000 2 \le n \le 10000 , 1 m 50000 1 \le m \le 50000 , 0 k 10 0≤k≤10 ,
0 c 10000 s , t < n 0 \le c \le 10000≤s,t<n , 0 a 0≤a , b < n b<n , a b a≠b , 0 c 1000 0≤c≤1000


今上午考試考了這道題,陣列開小了 Q A Q QAQ

這道題是分層圖最短路問題
就是說在最短路的基礎上有幾條邊的代價可以修改為零。

基本模型:

在給定的圖上,有k次機會可以直接通過一條邊,問起點與終點之間的最短路徑

這樣的題好像都挺裸的

做法是分層,
這裡詳細說一下吧

我們建立第 0 0 層至第 k k 層一共 k + 1 k+1 層圖,每一層的邊都是一樣的,第 i i 層表示用掉 i i 次機會所能到達的最小价值。

int u=read()+1,v=read()+1,w=read();//因為此題點從0開始,個人習慣從1開始,就+1
for(int j=0;j<=k;++j){
	add_edge(u+j*n,v+j*n,w);
	add_edge(v+j*n,u+j*n,w);//每n個一層
}

像這樣。

然後在每層圖之間建邊,因為有 k k 次機會,所以,把第 i i 層的節點建一條通往 i + 1 i+1 層的邊,邊權為 0 0

for(int j=0;j<k;++j)
	add_edge(u+j*n,v+j*n+n,0),add_edge(v+j*n,u+j*n+n,0);

至此,邊就建完啦!

然後就是一個一丁都不用改的最短路(個人推薦堆優 d i j k s t r a dijkstra )

(關於SPFA,它死了)

對了!點陣列的大小要開 k + 1 k+1 倍!上午考試只開了 k k 倍掛了一個點 Q A Q QAQ

奉上完整程式碼:

#include<iostream>
#include<cstdio>
#include<ctype.h>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef pair<int,int> pairs;
priority_queue<pairs,vector<pairs>,greater<pairs> > q;
inline int read(){
	int x=0,f=0;char ch=getchar();
	while(!isdigit(ch))f|=ch=='-',ch=getchar();
	while(isdigit(ch))x=x*10+(ch^48),ch=getchar();
	return f?-x:x;
}
int head[110007],cnt;
bool vis[110007];
int dis[110007];
int n,m,k,s,t,ans=99999999;
struct Edge{
	int next,to,w;
}edge[20000007];
inline void add_edge(int from,int to,int w){
	edge[++cnt].next=head[from];edge[cnt].w=w;
	edge[cnt].to=to;head[from]=cnt;
}
inline void dijkstra(){
	memset(dis,0x3f,sizeof dis);
	dis[s]=0;q.push(make_pair(dis[s],s));
	while(!q.empty()){
		int x=q.top().second;q.pop();
		if(vis[x])continue;vis[x]=1;
		for(int i=head[x];i;i=edge[i].next){
			int to=edge[i].to;
			if(dis[to]>dis[x]+edge[i].w){
				dis[to]=dis[x]+edge[i].w;
				q.push(make_pair(dis[to],to));
			}
		}
	}
}
int main(){
//	freopen("pass.in","r",stdin);
//	freopen("pass.out","w",stdout);
	n=read(),m=read(),k=read();
	s=read()+1,t=read()+1;
	for(int i=1;i<=m;++i){
		int u=read()+1,v=read()+1,w=read();
		for(int j=0;j<k;++j)add_edge(u+j*n,v+j*n+n,0),add_edge(v+j*n,u+j*n+n,0);
		for(int j=0;j<=k;++j){
			add_edge(u+j*n,v+j*n,w);
			add_edge(v+j*n,u+j*n,w);
		}
	}
	dijkstra();
	for(int i=0;i<=k;++i)ans=min(ans
            
           

相關推薦

luogu P4568 [JLOI2011]飛行路線 題解

www. ons rom isdigit urn tdi n) ios sizeof 題目鏈接:https://www.luogu.org/problemnew/show/P4568 卡了一晚上,算是分層圖最短路的模板。註意卡SPFA,所以我寫了個SLF優化。 同時 AC4

luogu P4568 [JLOI2011]飛行路線

fin har tchar define math continue ret cpp name 傳送門 看到免費次數\(k\)最多只有10,可以考慮構建\(k+1\)層的分層圖,即每一層正常連邊,上下兩層對應點連邊權為0的單向邊,最後對所有層裏面的\(di_t\)取\(\m

BZOJ 2163JLOI2011飛行路線分層短路

據說這個叫分層圖最短路 是個常見套路 一般就是:有k次機會可以直接通過一條邊,問起點與終點之間的最短路徑 我的理解:就相當給dis和inque陣列加了一維表示用了j次免費機會 然後在鬆弛的時候就有兩種決策:1.走免費邊 2.走要錢的邊 8102年了 別寫spfa了 #include<bits/stdc+

洛谷P4568 [JLOI2011]飛行路線分層短路

題目描述 AliceAliceAlice和BobBobBob現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在nnn個城市設有業務,設這些城市分別標記為000到n−1n-1n−1,一共有mmm種航線,每種航線連線兩個城市,並且航線有一定的價格。

JLOI2011」「LuoguP4568」飛行路線分層短路

題目描述 Alice和Bob現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在nn個城市設有業務,設這些城市分別標記為00到n-1n−1,一共有mm種航線,每種航線連線兩個城市,並且航線有一定的價格。 Alice和Bob現在要從一個城市沿著航線到達另一個城市,途中可以進行轉機。航空公司對

題解洛谷P1144短路計數 spfa

題目連結 spfa跑單源最短路,注意相等時線路數相加。 #include<cstdio> #include<cstring> #include<queue> using namespace std; const int

bzoj 2763: [JLOI2011]飛行路線分層+spfa

inf stream std 之間 using clas emp queue name 為什麽早年的題總是從0開始標號啊……又zz了一次WA 分層圖的題只有這一個套路吧,建分層圖,然後優化時間是分層跑spfa然後層與層之間單獨跑即可 #include<iostream

洛谷 P4568 [JLOI2011]飛行路線 解題報告

clas amp 設有 ret 另一個 turn ali struct 6.2 P4568 [JLOI2011]飛行路線 題目描述 Alice和Bob現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在\(n\)個城市設有業務,設這些城市分別標記為0到\(n

p4568 [JLOI2011]飛行路線

ans use code 表示 直接 城市 string cst 現在 Description Alice和Bob現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在nn個城市設有業務,設這些城市分別標記為\(0\)到\(n?1\),一共有\(m\)種航線

C++ P4568 [JLOI2011]飛行路線 ---- Dijkstra+分層

題目地址:https://www.luogu.org/problemnew/show/P4568 Dijkstra:https://blog.csdn.net/u012972031/article/details/83476580 分層圖是什麼 顧名思義,所謂的"分層圖",就是分

P4568 [JLOI2011]飛行路線 分層+dijkstra

題目連結 這個題就是分層思想的板子題,簡而言之,分層思想就是通過狀態轉移的方式進行維數上的轉移 盜一張@EternalAlexander 的圖方便理解(樣例)     這裡只有一個免費限制,所以是一個兩層的三維圖。 // luogu-judger-e

Luogu P2695 騎士的工作題解

題目背景 你作為一個村的村長,保衛村莊是理所當然的了.今天,村莊裡來了一隻惡龍,他有 n n n個頭,惡

Luogu P2622 關燈問題II題解

題目描述 現有 n n n盞燈,以及

[BZOJ2763][JLOI2011]飛行路線(分層短路)

div 宋體 define struct 所有 void code printf string 求S到T的最短路,中間最多k條邊可以不計代價。 顯然可以f[i][j]表示當前在點i,已有j條邊不計代價的最小代價,SPFA解決。 NOI2018後顯然不能寫SPFA,考慮為

BZOJ2763: [JLOI2011]飛行路線(分層 短路)

題意 題目連結 Sol 分層圖+最短路 建\(k+1\)層圖,對於邊\((u, v, w)\),首先在本層內連邊權為\(w\)的無向邊,再各向下一層對應的節點連邊權為\(0\)的有向邊 如果是取最大最小值的話可以考慮二分答案+最短路 // luogu-judger-enable-o2 // luo

[BZOJ2763] [JLOI2011] 飛行路線 [分層短路]

link 多開一維表示層數(免費坐了幾次) #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include&

SDOI2009Elaxia的路線拓撲+短路+dp

先找出Elaxia的最短路 重新建圖 在此圖上我們再標記同時也是w**的最短路的邊 顯然這是一個DAG 可以做dp 設f[i]表示以i點結尾的最長公共連續和(公共路徑一定是一條鏈) 則f[vis]=max(f[now],f[now]+e[u].val*e[u].flag)(flag表示是否也是w**的最短路)

[BZOJ2763][JLOI2011][分層短路]飛行路線

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

P4568 飛行路線 分層短路

gist 問題 class spl reg cpp define names inline P4568 飛行路線 分層圖最短路 分層圖最短路 問題模型 求最短路時,可有\(k\)次更改邊權(減為0) 思路 在普通求\(Dijkstra\)基礎上,\(dis[x][j]\)多