题意:在可选择k个边花费为0的情况下求最短路
思路:最短路dis数组增加一维表示使用免费的次数,判断最短路时,分两种情况,使用免费次数或不使用。
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f;
const int maxn = 1e5 + 10;
struct Edge//邻接表
{
int to,w,next;
}G[maxn];
int vis[maxn][12];
int dis[maxn][12];//第二维表示的使用免费机会的次数
int head[maxn];
int cnt,n,m,k,st,ed;
void init()
{
memset(vis,0,sizeof vis);
for(int i = 0 ;i <= n; i++)
{
for(int j = 0 ; j <= k; j++)
{
dis[i][j] = inf;
}
head[i] = -1;
}
cnt = 0;
}
void addEdge(int s,int e,int w)
{
G[cnt].to = e;
G[cnt].w = w;
G[cnt].next = head[s];
head[s] = cnt++;
}
void SPFA()
{
dis[st][0] = 0;
vis[st][0] = 1;
queue<pair<int,int> > que;
que.push(make_pair(st,0));
while(!que.empty())
{
pair<int,int> t = que.front();
que.pop();
vis[t.first][t.second] = 0;
for(int i = head[t.first];i != -1; i = G[i].next)
{
if(dis[t.first][t.second] +G[i].w < dis[G[i].to][t.second])//不使用免费机会的最短路
{
dis[G[i].to][t.second] = dis[t.first][t.second] +G[i].w;
if(!vis[G[i].to][t.second])
{
vis[G[i].to][t.second] = 1;
que.push(make_pair(G[i].to,t.second));
}
}
if(dis[t.first][t.second] < dis[G[i].to][t.second+1]&&t.second < k)//使用免费机会的最短路
{
dis[G[i].to][t.second+1] = dis[t.first][t.second];
if(!vis[G[i].to][t.second+1])
{
vis[G[i].to][t.second+1] = 1;
que.push(make_pair(G[i].to,t.second+1));
}
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
while(cin>>n>>m>>k)
{
init();
cin>>st>>ed;
for(int i = 0; i < m; i++)
{
int u,v,w;
cin>>u>>v>>w;
addEdge(u,v,w);
addEdge(v,u,w);
}
SPFA();
cout<<dis[ed][k]<<endl;
}
return 0;
}