JLOI2011 飞行路线 分层图+最短路

起初不知道分层图的概念,做了以后才发现哦原来这就是分层图啊

分层图的概念:将一个复杂的图分层,有点像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;
}

关于SPFA

  • 他死了

你可能感兴趣的:(图论,最短路,分层图)