题目链接:https://nanti.jisuanke.com/t/31001
题意:可以选择k条边使其边权为0,求1到n的最短路
题解:分层图+dijkstra,建立k层图,不同层之间的路为0
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int MAX=5e6+10;
int n,m,k,head[MAX],cnt=0;
ll dis[MAX];
bool vis[MAX];
struct edge{
int to,w,next;
}E[MAX];
void add(int a,int b,int c){
E[cnt].to=b;
E[cnt].w=c;
E[cnt].next=head[a];
head[a]=cnt++;
}
struct node{
int id;
ll d;
bool operator < (const node &a) const {
return d>a.d;
}
node(int _id,ll _d){
this->d=_d;
this->id=_id;
}
};
void Dijkstra(){
memset(dis,inf,sizeof dis);
memset(vis,0,sizeof vis);
priority_queue<node>q;
dis[1]=0;
q.push(node(1,0));
while(!q.empty()){
node t=q.top();q.pop();
int id=t.id;
vis[id]=true;
for(int i=head[id];~i;i=E[i].next){
int to=E[i].to;
if(vis[to]) continue;
if(dis[to]>dis[id]+E[i].w){
dis[to]=dis[id]+E[i].w;
q.push(node(to,dis[to]));
}
}
}
}
int main(){
int T,a,b,c;
scanf("%d",&T);
while(T--){
memset(head,-1,sizeof head);cnt=0;
scanf("%d%d%d",&n,&m,&k);
while(m--){
scanf("%d%d%d",&a,&b,&c);
for(int i=0;i<=k;i++){
add(a+n*i,b+n*i,c);//构造k+1层图上的边
if(i!=k) add(a+n*i,b+n*(i+1),0);
}
}
Dijkstra();
ll ans=inf;
for(int i=0;i<=k;i++){
ans=min(ans,dis[n+n*i]);
}
printf("%lld\n",ans);
}
return 0;
}