[BZOJ2763][JLOI2011][分層圖最短路]飛行路線
阿新 • • 發佈:2019-01-28
<題目>
Alice和Bob現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在n個城市設有業務,設這些城市分別標記為0到n-1,一共有m種航線,每種航線連線兩個城市,並且航線有一定的價格。Alice和Bob現在要從一個城市沿著航線到達另一個城市,途中可以進行轉機。航空公司對他們這次旅行也推出優惠,他們可以免費在最多k種航線上搭乘飛機。那麼Alice和Bob這次出行最少花費多少?
<演算法>
分層圖最短路 堆優化的Dijkstra
<分析>
乍一看是最短路,再仔細一看用最短路似乎無法實現。分層圖可以很巧妙的解決這個問題。想象你每次使用免費航線之前和之後分別存在於不同的時空(不同的層)裡面,每使用一次免費航線,你就從這個時空進入了另一個時空(免費)。根據以上思想建圖,一共建k+1層圖,相鄰的兩層圖中進行連邊(單向邊,距離為1)。然後跑dijkstra即可
<注意>
-
分層圖思想~
-
spfa會超時。我用的是stl裡面的priority_queue寫堆j。注意priority_queue裡面不用front()而是top。而且需要重定義結構體的operator<
<鳴謝>
感謝zky的題解
<程式碼>
/************************************************************** Problem: 2763 User: gaotianyu1350 Language: C++ Result: Accepted Time:512 ms Memory:38320 kb ****************************************************************/ #include #include #include #include #include #include using namespace std; #define MAXNODE 200100 #define MAXEDGE 3000000 #define INF 1000000000 struct Node { int dis,u; bool operator<(const Node x)const { return dis>x.dis; } }; int point[MAXNODE]={0},w[MAXEDGE],next[MAXEDGE]={0},v[MAXEDGE],tot; int dis[MAXNODE]; bool check[MAXNODE]; priority_queue q; int n,m,k; void addedge(int x,int y,int cost) { tot++; next[tot]=point[x];point[x]=tot;v[tot]=y;w[tot]=cost; } int dijkstra(int s,int t) { memset(dis,0x7f,sizeof(dis)); memset(check,0,sizeof(check)); while (!q.empty()) q.pop(); dis[s]=0;q.push((Node){0,s}); while (!q.empty()) { Node now=q.top();q.pop(); if (check[now.u]) continue; check[now.u]=true; for (int temp=point[now.u];temp;temp=next[temp]) if (dis[now.u]+w[temp]