题意:还是单源最短路问题,不过不同的是你可以任选至多k条边并将它们的权值变成0。
思路:这是一类问题,我们可以把原图复制k边,形成k层,我们在每一次加边的时候不但要加上本来的边,还将n层图之间的u,v相连,权值为0,相当于一条快速下滑通道。因为图最多k层,所以最多只能使用k次下滑通道。你可能会觉得非常难实现,其实这本质上和经典的最短路没有区别,只是边更多了。
RE了无数次,因为不光边多了,额外加边的时候,相当于每个点有了”分身”。
AC代码:
/**************************************************************
Problem: 2763
User: Dicer
Language: C++
Result: Accepted
Time:984 ms
Memory:103964 kb
****************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int ,int> pii;
const int INF = 0x3f3f3f3f;
const int N = 5e6+10;
const int M = 5e6+10;
struct EDGE{
int next;
int to;
int w;
}edge[M];
int n,m,k,s,e,cnt = 1;
int head[N],dis[N];
bool inq[N];
void add(int u, int v, int w){
edge[cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].w = w;
head[u] = cnt++;
}
struct NODE{
int id,dist;
}q,p;
bool operator < (NODE a, NODE b){
return a.dist > b.dist;
}
void Dijkstra(){
memset(dis, INF, sizeof dis);
memset(inq, 0, sizeof inq);
priority_queue<NODE> que;
p.id = s; p.dist = 0;
dis[s] = 0; que.push(p);
while(!que.empty()){
q = que.top(); que.pop();
if(inq[q.id]) continue;
inq[q.id] = true;
for(int i=head[q.id]; ~i; i=edge[i].next){
int u = edge[i].to;
if(dis[u] > q.dist + edge[i].w){
dis[u] = q.dist + edge[i].w;
p.id = u;
p.dist = dis[u];
que.push(p);
}
}
}
int ans = INF;
for(int i=0; i<=k; ++i) ans = min(ans, dis[e + i*n]);
printf("%d\n", ans);
}
int main(int argc, char const *argv[])
{
int u, v, w;
memset(head, -1, sizeof head);
scanf("%d %d %d %d %d",&n, &m, &k, &s, &e);
for(int i=1;i<=m;++i){
scanf("%d %d %d",&u, &v, &w);
for(int j=0; j<=k; ++j){
add(u + j*n, v + j*n, w);
add(v + j*n, u + j*n, w);
if(j != k){
add(u + j*n, v + (j+1)*n, 0);
add(v + j*n, u + (j+1)*n, 0);
}
}
}
Dijkstra();
return 0;
}