题目连接:https://ac.nowcoder.com/acm/problem/20131
思路:
建立原图的基础上再建立k个分身,每个分身之间的权值为0,用dijkstra算起始点到各点的距离,注意k次免费的机会不一定都使用。
画个图大家就明白了。
这就相当于在用掉最多k次免费机会的前提下 求最短路
code:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int,int> PII;
const int N=5e6+10;
int head[N],w[N],e[N],ne[N];
int dis[N],st[N];//dis 记录每个点到1最短距离 st记录每个点是否在队列中
int n,m,cnt,k;
void add(int u,int v,int val){//链式前向星加边
e[cnt]=v,w[cnt]=val,ne[cnt]=head[u],head[u]=cnt++;
}
void dijkstra(int u){
memset(dis,INF,sizeof(dis));
dis[u]=0;
priority_queue<PII,vector<PII>,greater<PII> > heap;
heap.push({0,u});
while(heap.size()){
auto t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver]) continue;
st[ver]=1;
for(int i=head[ver];i!=-1;i=ne[i]){
int v=e[i];
if(dis[v]>distance+w[i]){
dis[v]=distance+w[i];
heap.push({dis[v],v});
}
}
}
}
int main()
{
memset(head,-1,sizeof(head));
int u,v;
cin>>n>>m>>k;
cin>>u>>v;
int a ,b,c;
while(m--){
cin>>a>>b>>c;
for(int i=0;i<=k;i++){
add(a+i*n,b+i*n,c);
add(b+i*n,a+i*n,c);
if(i!=k){
add(a+i*n,b+(i+1)*n,0);//俩个分身之间权值为0
add(b+i*n,a+(i+1)*n,0);
}
}
}
dijkstra(u);
int ans=INF;
for(int i=0;i<=k;i++){//因为k次机会不一定都要使用,取个最小的就行了
ans=min(ans,dis[v+i*n]);
}
cout<<ans<<endl;
return 0;
}