zoukankan      html  css  js  c++  java
  • P4568 飞行路线 分层图最短路

    P4568 飞行路线 分层图最短路

    分层图最短路

    问题模型

    求最短路时,可有(k)次更改边权(减为0)

    思路

    在普通求(Dijkstra)基础上,(dis[x][j])多开一维(j)以存已用了多少次机会,然后每次松弛时,做完普通松弛操作后,还要使用一次机会(如果可以),类同(DP)

    每次普通松弛:

    [dis[to][j]=min{dis[cur][j], dis[to][j]} ]

    如果还可以使用((j<k)):

    [dis[to][j+1] = min{dis[cur][j], dis[to][j+1]} ]

    AC Code:

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <queue>
    #define MAXN 10010
    #define MAXK 11
    #define MIN(A,B) ((A)<(B)?(A):(B))
    using namespace std;
    int n,m,k,s,e;
    bool vis[MAXN][MAXK];
    struct edge{
        int v,w;
        edge(int v, int w):v(v),w(w){}
    };
    vector <edge> mp[MAXN];
    struct item{
        int dis, k, v;
        item(int dis, int k, int v):dis(dis), k(k), v(v){}
        bool operator < (const item a) const{
            return dis > a.dis;
        }
    };
    int dis[MAXN][MAXK];
    priority_queue <item> q;
    void Dij(){
        memset(dis, 0x3f, sizeof(dis));
        dis[s][0]=0;
        q.push(item(0,0,s));
        while(!q.empty()){
            item cur = q.top();q.pop();
            if(vis[cur.v][cur.k]) continue;
            vis[cur.v][cur.k] = 1;
            for(register int i=0;i<mp[cur.v].size();++i){
                int v = mp[cur.v][i].v, w = mp[cur.v][i].w;
                if(cur.k<k&&!vis[v][cur.k+1]&&dis[v][cur.k+1]>dis[cur.v][cur.k]){ // 使用机会
                    dis[v][cur.k+1] = dis[cur.v][cur.k];
                    q.push(item(dis[v][cur.k+1], cur.k+1, v));
                }
                if(!vis[v][cur.k]&&dis[v][cur.k]>dis[cur.v][cur.k]+w){ // 普通松弛
                    dis[v][cur.k] = dis[cur.v][cur.k]+w;
                    q.push(item(dis[v][cur.k], cur.k, v));
                }
            }
        }
    }
    int main()
    {
        scanf("%d %d %d %d %d", &n, &m, &k, &s, &e),s++,e++;
        for(int i=1;i<=m;++i){
            int a,b,c;
            scanf("%d %d %d", &a, &b, &c),++a,++b;
            mp[a].push_back(edge(b,c));
            mp[b].push_back(edge(a,c));
        }
        Dij();
        int ans=0x3ffffff;
        for(int i=0;i<=k;++i)
            ans = MIN(ans, dis[e][i]); // 遍历统计答案,机会不一定用完
        printf("%d", ans);
        return 0;
    }
    
  • 相关阅读:
    对MVC模式与MVVM模式的认识
    优雅降级和渐进增强
    入园第一天
    看看AQS阻塞队列和条件队列
    简单看看LockSupport和AQS
    简单看看LongAccumulator
    JUC中的原子操作类及其原理
    java并发基础知识
    简单看看es6解构赋值
    简单使用vue-cli
  • 原文地址:https://www.cnblogs.com/santiego/p/10803284.html
Copyright © 2011-2022 走看看