1. 程式人生 > >[BZOJ2763][JLOI2011][分層圖最短路]飛行路線

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

<題目>

Alice和Bob現在要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在n個城市設有業務,設這些城市分別標記為0到n-1,一共有m種航線,每種航線連線兩個城市,並且航線有一定的價格。Alice和Bob現在要從一個城市沿著航線到達另一個城市,途中可以進行轉機。航空公司對他們這次旅行也推出優惠,他們可以免費在最多k種航線上搭乘飛機。那麼Alice和Bob這次出行最少花費多少?

<演算法>

分層圖最短路 堆優化的Dijkstra

<分析>

乍一看是最短路,再仔細一看用最短路似乎無法實現。分層圖可以很巧妙的解決這個問題。想象你每次使用免費航線之前和之後分別存在於不同的時空(不同的層)裡面,每使用一次免費航線,你就從這個時空進入了另一個時空(免費)。根據以上思想建圖,一共建k+1層圖,相鄰的兩層圖中進行連邊(單向邊,距離為1)。然後跑dijkstra即可

<注意>

  1. 分層圖思想~

  2. 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]