起初不知道分层图的概念,做了以后才发现哦原来这就是分层图啊
分层图的概念:将一个复杂的图分层,有点像DP中的状态,把跳到下一层的条件认为是状态转移,然后直接一遍最短路。
由于标准的分层图空间太大,所以直接在原图进行转移了(更像DP了不是吗)
SPFA(被安排了)
#include
#include
#include
#include
using namespace std;
const int MAXN = 10001;
const int MAXM = 50001;
int n, m, k;
int fir[MAXN], nxt[MAXM << 1], to[MAXM << 1], len[MAXM << 1], cnt;
int dis[MAXN][11], vis[MAXN][11];
inline int read(){
int k = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
return k * f;
}
inline void add_edge(int a, int b, int l){
len[cnt] = l, to[cnt] = b, nxt[cnt] = fir[a], fir[a] = cnt++;
}
void SPFA(int u){
int t;
queue <int> q1; q1.push(u);
queue <int> q2; q2.push(0);
memset(vis, 0, sizeof(vis)); vis[u][0] = true;
memset(dis, 0x3f, sizeof(dis)); dis[u][0] = 0;
while(!q1.empty()){
u = q1.front(); q1.pop();
t = q2.front(); q2.pop();
vis[u][t] = false;
for(int i = fir[u]; i != -1; i = nxt[i]){
int v = to[i], flag = false;
if(dis[v][t] > dis[u][t] + len[i]){
dis[v][t] = dis[u][t] + len[i];
if(!vis[v][t]) q1.push(v), q2.push(t), vis[v][t] = true;
}
if(t < k && dis[v][t + 1] > dis[u][t]){
dis[v][t + 1] = dis[u][t];
if(!vis[v][t + 1]) q1.push(v), q2.push(t + 1), vis[v][t + 1] = true;
}
}
}
}
int main(){
memset(fir, -1, sizeof(fir));
n = read(), m = read(), k = read();
int Begin = read(), End = read();
for(int i = 1; i <= m; i++){
int a = read(), b = read(), l = read();
add_edge(a, b, l);
add_edge(b, a, l);
}
SPFA(Begin);
int ans = 0x7fffffff;
for(int i = 0; i <= k; i++) ans = min(ans, dis[End][i]);
printf("%d", ans);
return 0;
}
后来写的Dijkstra
#include
#include
#include
#include
using namespace std;
const int MAXN = 10001;
const int MAXM = 50001;
int n, m, k;
int fir[MAXN], nxt[MAXM << 1], to[MAXM << 1], len[MAXM << 1], cnt;
int dis[MAXN][11];
//int vis[MAXN][11];
inline int read(){
int k = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
return k * f;
}
inline void add_edge(int a, int b, int l){
len[cnt] = l, to[cnt] = b, nxt[cnt] = fir[a], fir[a] = cnt++;
}
struct Node{
int dis, u, t;
bool operator < (const Node & a) const{
return dis > a.dis;
}
};
void Dijkstra(int Begin){
priority_queue q; q.push((Node){0, Begin, 0});
// memset(vis, 0, sizeof(vis)); vis[Begin][0] = true;
memset(dis, 0x3f, sizeof(dis)); dis[Begin][0] = 0;
while(!q.empty()){
Node u = q.top(); q.pop();
// vis[u.dis][u.t] = true;
if(u.dis != dis[u.u][u.t]) continue;
for(int i = fir[u.u]; i != -1; i = nxt[i]){
int v = to[i];
if(dis[v][u.t] > dis[u.u][u.t] + len[i]){
dis[v][u.t] = dis[u.u][u.t] + len[i];
q.push((Node){dis[v][u.t], v, u.t});
}
if(u.t < k && dis[v][u.t + 1] > dis[u.u][u.t]){
dis[v][u.t + 1] = dis[u.u][u.t];
q.push((Node){dis[v][u.t + 1], v, u.t + 1});
}
}
}
}
int main(){
// freopen("flight.in", "r", stdin);
// freopen("flight.out", "w", stdout);
memset(fir, -1, sizeof(fir));
n = read(), m = read(), k = read();
int Begin = read(), End = read();
for(int i = 1; i <= m; i++){
int a = read(), b = read(), l = read();
add_edge(a, b, l);
add_edge(b, a, l);
}
Dijkstra(Begin);
int ans = 0x7fffffff;
for(int i = 0; i <= k; i++) ans = min(ans, dis[End][i]);
printf("%d", ans);
return 0;
}