[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] 
           
          
         
       
      
      
     
     
    
    
   
   


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值