zoukankan      html  css  js  c++  java
  • BZOJ:2763-[JLOI2011]飞行路线(最短路分层图)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2763


    解题心得:

    • 第一次见到分层最短路。其实题中说选择k条路径免费,那怎么选k条路径并没有一个明确的选法,就只能遍历。分层图就是一个图分成k层,每个节点可以走当前层的相邻节点,费用为cost,但是也可以走下一层的相邻节点,费用为0,因为只有k层,所以从第0层的S到达第k层的T也就走了k个免费路径。这个时候K不能太大,不然容易MLE。
    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 5e5+100;
    const ll INF = 1e12;
    
    ll n, m, k, S, T;
    
    struct edge {
        ll to, len;
    
        edge(ll to1, ll len1):
                to(to1), len(len1){};
    };
    
    struct NODE {//记录队列中节点的位置,层数,花费
        ll len, pos, c;
    
        bool friend operator < (NODE a, NODE b) {
            return a.len > b.len;
        }
    
        NODE (ll len1, ll pos1, ll c1):
                len(len1), pos(pos1), c(c1){};
    };
    
    vector <edge> ve[maxn];
    
    ll dis[11][maxn];
    
    void add_edge(ll u, ll v, ll len) {//注意是双向边
        ve[u].push_back(edge(v, len));
        ve[v].push_back(edge(u, len));
    }
    
    void init() {
        for(int i=0;i<11;i++)
            for(int j=0;j<maxn;j++)
                dis[i][j] = INF;
    
        scanf("%lld%lld%lld",&n,&m,&k);
        scanf("%lld%lld",&S, &T);
        for(int i=0;i<m;i++) {
            ll u, v, len;
            scanf("%lld%lld%lld",&u, &v, &len);
            add_edge(u, v, len);
        }
    }
    
    void dij() {//用dij不容易被卡网格图
        priority_queue <NODE> qu;
        qu.push(NODE(0, S, 0));
        dis[0][S] = 0;
        while(!qu.empty()) {
            NODE now = qu.top(); qu.pop();
            ll u = now.pos;
            for(int i=0;i<ve[u].size();i++) {//走当前层
                ll v = ve[u][i].to;
                ll len = ve[u][i].len;
                ll c = now.c;
                if(dis[c][v] > dis[c][u]+len) {
                    dis[c][v] = dis[c][u] + len;
                    qu.push(NODE(dis[c][v], v, c));
                }
            }
    
            ll c = now.c;
            if(c < k) {//走下一层
                for (int i = 0; i < ve[u].size(); i++) {
                    ll v = ve[u][i].to;
                    if(dis[c+1][v] > dis[c][u]) {//花费为0
                        dis[c+1][v] = dis[c][u];
                        qu.push(NODE(dis[c][u], v, c+1));
                    }
                }
            }
        }
    }
    
    void min_path() {
        dij();
        ll Min = INF;
        for(int i=0;i<=k;i++) {
            Min = min(Min, dis[i][T]);
        }
        printf("%lld
    ", Min);
    }
    
    int main() {
        init();
        min_path();
    }
  • 相关阅读:
    可惜CodeSmith不直接支持Oracle数据库对象...
    Windows Vista
    关于Web Service ...
    他赚了多少钱?
    关于CodeSmith中模板的属性编辑...
    关于Session超时...
    奇怪的CheckBoxList...
    Devdays 2006 China | 微软开发者日
    第二阶段冲刺第一次会议
    冲刺阶段第一天
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9574230.html
Copyright © 2011-2022 走看看