Luogu P4568 [JLOI2011]飛行路線【題解】(分層圖最短路模板)
題目描述
和 現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在 個城市設有業務,設這些城市分別標記為 到 ,一共有 種航線,每種航線連線兩個城市,並且航線有一定的價格。
和 現在要從一個城市沿著航線到達另一個城市,途中可以進行轉機。航空公司對他們這次旅行也推出優惠,他們可以免費在最多 種航線上搭乘飛機。那麼 和 這次出行最少花費多少?
輸入輸出格式
輸入格式:
資料的第一行有三個整數,
,
,
,分別表示城市數,航線數和免費乘坐次數。
第二行有兩個整數,
,
,分別表示他們出行的起點城市編號和終點城市編號。
接下來有m行,每行三個整數,
,
,
,表示存在一種航線,能從城市
到達城市
,或從城市
到達城市
,價格為
。
輸出格式:
只有一行,包含一個整數,為最少花費。
輸入輸出樣例
輸入樣例#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%的資料,
,
,
,
對於50%的資料,
,
,
;
對於100%的資料,
,
,
,
,
,
,
,
今上午考試考了這道題,陣列開小了
這道題是分層圖最短路問題
就是說在最短路的基礎上有幾條邊的代價可以修改為零。
基本模型:
在給定的圖上,有k次機會可以直接通過一條邊,問起點與終點之間的最短路徑
這樣的題好像都挺裸的
做法是分層,
這裡詳細說一下吧
我們建立第 層至第 層一共 層圖,每一層的邊都是一樣的,第 層表示用掉 次機會所能到達的最小价值。
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個一層
}
像這樣。
然後在每層圖之間建邊,因為有 次機會,所以,把第 層的節點建一條通往 層的邊,邊權為 。
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);
至此,邊就建完啦!
然後就是一個一丁都不用改的最短路(個人推薦堆優 )
(關於SPFA,它死了)
對了!點陣列的大小要開 倍!上午考試只開了 倍掛了一個點
奉上完整程式碼:
#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]飛行路線【題解】(分層圖最短路模板)
題目描述
A
l
i
c
【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 2163】【JLOI2011】飛行路線(分層圖最短路)
據說這個叫分層圖最短路 是個常見套路 一般就是:有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&
【SDOI2009】Elaxia的路線(拓撲+最短路+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]\)多