题意:询问从1-n的最短路,可以选择k条路把他的长度变为0
题解:大概是一个动态规划的思想, dis[i][j] d i s [ i ] [ j ] 表示从1到i删除了j条边后的距离,然后得到转移方程 1、dis[v][j]=dis[u][j]+cost,2、dis[v][j+1]=dis[u][j] 1 、 d i s [ v ] [ j ] = d i s [ u ] [ j ] + c o s t , 2 、 d i s [ v ] [ j + 1 ] = d i s [ u ] [ j ] 然后在松弛的时候判断即可,卡spfa? dijkstra+堆优化可以AC
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
#define pb push_back
const int maxn = 2e5 + 10;
const ll inf = 1e18;
ll n, m, k, T, u, v, w;
struct EDGE {
EDGE(ll u, ll v, ll _w) : from(u), to(v), w(_w) {};
ll from, to, w;
};
struct NODE {
ll c, x, y;
NODE() {};
NODE(ll _id, ll _c, ll _k) : x(_id), c(_c), y(_k) {};
bool operator < (const NODE &r) const {
return c > r.c;
}
};
vector<EDGE> E[maxn];
bool vis[maxn][20];
ll dis[maxn][20];
void init() {
for(int i = 1; i <= n; i++) {
for(int j = 0; j < 20; j++) {
dis[i][j] = inf;
}
}
met(vis, false);
}
void addEdge(int u, int v, int w) {
E[u].pb(EDGE(u, v, w));
}
ll dijkstra(int n, int start, int en) {
priority_queue<NODE> q;
ll res = inf;
q.push(NODE(start, 0, 0));
dis[start][0] = 0;
while(!q.empty()) {
NODE t = q.top();
q.pop();
int x = t.x, y = t.y;
if(x == en) {
res = min(res, t.c);
//cout <<res <<endl;
}
if(vis[x][y]) continue;
vis[x][y] = true;
int len = E[x].size();
rep(i, 0, len - 1) {
int v = E[x][i].to;
int cost = E[x][i].w;
if(dis[v][y] > dis[x][y] + cost) {
dis[v][y] = dis[x][y] + cost;
if(!vis[v][y]) q.push(NODE(v, dis[v][y], y));
}
if(y + 1 <= k && dis[v][y + 1] > dis[x][y]) {
dis[v][y + 1] = dis[x][y];
if(!vis[v][y + 1]) q.push(NODE(v, dis[v][y + 1], y + 1));
}
}
}
return res;
}
int main() {
scanf("%lld", &T);
while(T--) {
scanf("%lld%lld%lld", &n, &m, &k);
init();
rep(i, 1, n) E[i].clear();
rep(i, 1, m) {
scanf("%lld%lld%lld", &u, &v, &w);
addEdge(u, v, w);
}
ll ans = dijkstra(n, 1, n);
printf("%lld\n", ans);
}
return 0;
}