题目描述
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]);
}