Flight Discount

题目描述

Your task is to find a minimum-price flight route from Syrjälä to Metsälä. You have one discount coupon, using which you can halve the price of any single flight during the route. However, you can only use the coupon once.

When you use the discount coupon for a flight whose price is x, its price becomes (it is rounded down to an integer).

输入

The first input line has two integers n and m: the number of cities and flight connections. The cities are numbered 1,2,...,n. City 1 is Syrjälä, and city n is Metsälä.

After this there are m lines describing the flights. Each line has three integers a, b, and c: a flight begins at city a, ends at city b, and its price is c. Each flight is unidirectional.

You can assume that it is always possible to get from Syrjälä to Metsälä.

Constraints

2 ≤ n ≤ 105

1 ≤ m ≤ 2*10^5

1 ≤ a,b ≤ n

1 ≤ c ≤ 109

输出

Print one integer: the price of the cheapest route from Syrjälä to Metsälä.

样例输入
复制代码
3 4
1 2 3
2 3 1
1 3 7
2 1 5
样例输出
复制代码
2

**题目大意:**要从1到n,有一张优惠券,可以让在1到n途中的某条路的价格变为一半(向下取整),求从1到n最小的价格

**思路:**dijkstra求最短路。加上优惠券,那就让d再多一个维度,用dij记录从1到i,j=0:还未使用优惠券时的最小价格,j=1:已经使用过优惠券的最小价格。

注意剪枝(即dijkstra模板中的s数组):加进队列中的这个价格(距离)已经更新过了

cpp 复制代码
if(dist>d[id][flag])
        continue;

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using tup=tuple<ll,int,int>;//距离,节点编号,是否用券
const int N=100010,M=200010;
int h[N],e[M],ne[M],idx;
ll w[M],d[N][2];//到节点i,0:不使用优惠券,1:使用
void add(int a,int b,int c){
    w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n,m;cin>>n>>m;
    memset(h,-1,sizeof(h));
    for (int i=0;i<m;i++){
        int a,b,c;cin>>a>>b>>c;
        add(a,b,c);
    }
    memset(d,0x3f,sizeof(d));
    d[1][0]=0;
    priority_queue<tup,vector<tup>,greater<tup>>pq;
    pq.emplace(0,1,0);
    while(!pq.empty()){
        auto [dist,id,flag]=pq.top();
        pq.pop();
        if(dist>d[id][flag])
        continue;
        for (int i=h[id];i!=-1;i=ne[i]){
            int j=e[i];
            if(flag==0){//还没有使用券
                //不用券
                if(d[j][0]>dist+w[i]){
                    d[j][0]=dist+w[i];
                    pq.emplace(d[j][0],j,0);
                }
                //用券
                if(d[j][1]>dist+w[i]/2){
                    d[j][1]=dist+w[i]/2;
                    pq.emplace(d[j][1],j,1);
                }
            }
            else{//已经使用了券
                if(d[j][1]>dist+w[i]){
                    d[j][1]=dist+w[i];
                    pq.emplace(d[j][1],j,1);
                }
            }
        }
    }
    cout<<min(d[n][0],d[n][1]);
}
相关推荐
叫我:松哥3 分钟前
基于Python flask的中学可控智能命题系统设计与实现,整合遗传算法、DeepSeek 大模型及数据库技术构建一体化应用
数据库·人工智能·python·算法·机器学习·flask·遗传算法
黎阳之光14 分钟前
黎阳之光透明大楼:实景孪生重构智慧建筑全新范式
人工智能·物联网·算法·安全·数字孪生
旖-旎1 小时前
《LeetCode 130 被围绕的区域 FloodFill DFS 解法》
c++·算法·深度优先·力扣·floodfill
林森lsjs1 小时前
斐波那契数列的 N 种解法:从递归到动态规划的优化之路【算法思考】
算法·动态规划
apcipot_rain2 小时前
计科八股20260616(1)——堆存中位数、链表判环、黑白测试、敏捷开发与瀑布模型、配置管理、持续集成、池化
数据结构·算法·软件工程
JAVA面经实录9179 小时前
Java 数据结构与算法 (终极完整学习文档)
java·数据结构·算法
开源Z10 小时前
LeetCode 42 · 接雨水:从暴力到双指针的三步优化
算法·leetcode
旖-旎11 小时前
《LeetCode 695 岛屿的最大面积 FloodFill DFS 解法》
c++·算法·力扣·深度优先遍历·floodfill
syagain_zsx11 小时前
STL 之 vector 讲练结合
c++·算法