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再多一个维度,用d[i][j]记录从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]);
}
相关推荐
张登杰踩几秒前
MCR ALS 多元曲线分辨算法详解
算法
YuTaoShao9 分钟前
【LeetCode 每日一题】3634. 使数组平衡的最少移除数目——(解法一)排序+滑动窗口
算法·leetcode·排序算法
波波00717 分钟前
每日一题:.NET 的 GC是如何分代工作的?
算法·.net·gc
风暴之零27 分钟前
变点检测算法PELT
算法
深鱼~27 分钟前
视觉算法性能翻倍:ops-cv经典算子的昇腾适配指南
算法·cann
李斯啦果28 分钟前
【PTA】L1-019 谁先倒
数据结构·算法
梵刹古音33 分钟前
【C语言】 指针基础与定义
c语言·开发语言·算法
啊阿狸不会拉杆1 小时前
《机器学习导论》第 5 章-多元方法
人工智能·python·算法·机器学习·numpy·matplotlib·多元方法
R1nG8632 小时前
CANN资源泄漏检测工具源码深度解读 实战设备内存泄漏排查
数据库·算法·cann
_OP_CHEN2 小时前
【算法基础篇】(五十六)容斥原理指南:从集合计数到算法实战,解决组合数学的 “重叠难题”!
算法·蓝桥杯·c/c++·组合数学·容斥原理·算法竞赛·acm/icpc