题目链接:Adventure of Super Mario UVA - 10269
题目大意:n个地点,前A个为村庄,后B个为城堡,马里奥要从第B个城堡到第A个村庄。另外马里奥有一双魔法靴,可以不耗费时间的走最多L长度,但是靴子的起始位置都必须是村庄或城堡且中途不能经过城堡。魔法靴最多可以使用K次。
先用Floyd求一个多源最短路,但是要保证每条最短路不会中途经过城堡。再用Dijkstra求出从第B个城堡到第A个村庄的最短路。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N=1e2+5;
const int inf=0x3f3f3f3f;
struct Node{
int to,w,cnt;
Node(){}
Node(int to,int w,int cnt): to(to),w(w),cnt(cnt){}
bool operator <(const Node &a)const{
return w>a.w;
}
};
int f[N][N],dis[N][15];
vector<Node> g[N];
int A,B,K,T,L,n,m;
void Floyd(){
for(int k=1;k<=A;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
void Dijkstra(){
priority_queue<Node> q;
dis[n][0]=0;
q.push(Node(n,0,0));
while(!q.empty()){
Node now=q.top(); q.pop();
for(int i=0;i<(int)g[now.to].size();i++){
int to=g[now.to][i].to, w=g[now.to][i].w;
if(dis[to][now.cnt]>dis[now.to][now.cnt]+w){
dis[to][now.cnt]=dis[now.to][now.cnt]+w;
q.push(Node(to,dis[to][now.cnt],now.cnt));
}
}
if(now.cnt>=K) continue;
for(int i=1;i<=n;i++){
int to=i;
if(dis[to][now.cnt+1]>dis[now.to][now.cnt]&&f[now.to][to]<=L){
dis[to][now.cnt+1]=dis[now.to][now.cnt];
q.push(Node(to,dis[to][now.cnt+1],now.cnt+1));
}
}
}
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d%d",&A,&B,&m,&L,&K);
n=A+B;
memset(f,inf,sizeof(f));
memset(dis,inf,sizeof(dis));
for(int i=1;i<=n;i++) f[i][i]=0, g[i].clear();
int u,v,w;
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
f[u][v]=f[v][u]=w;
g[u].push_back(Node(v,w,0));
g[v].push_back(Node(u,w,0));
}
Floyd();
Dijkstra();
int ans=inf;
for(int i=0;i<=K;i++)
ans=min(ans,dis[1][i]);
printf("%d\n",ans);
}
return 0;
}