2018 NanJing ICPC Online Contest L Magical Girl Haze (BZOJ - 2763) 分层最短路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38013346/article/details/82313662

Description

分层图最短路,就是在分层图上解决最短路问题。
主要是应用于变化的最短路问题,问题常表现为一个最短路问题上加一些手脚,如减小一些边权,改变一些连接,但事先又不知道,或可以自由选择改变哪个边,最终求最短路等等。由于无法知道改变了那些边,所以用到分层图思想。
$1.一种解决方法是多开一维记录状态,多开的维度记录状态的种类数即为分层数。 $
2. 西 k 2.另一种解决方法是可以理解为平行宇宙 一样的东西 就是把原图复制出来k个,然后在原图 连接的基础上,在相邻层中间加一些要求的变化边,通常是单向的(保证从每一层到下一层不再回来),再跑最短路。

M L E 个人觉得第一种更好一点。第二种方法需多建很多点和边,容易MLE。
B Z O J 2763 本题就是取自于BZOJ2763,不过是有向边且数据范围扩大了。
1 n 使 K 题意就是从1 \to n的最短路径长度,其中最多可以使得K条路径免费。


Input

1 T 5 1 \leq T\leq 5
N 1 0 5 N\leq 10^5
M 2 1 0 5 M\leq 2*10^5
K 10 K\leq 10
0 c i 1 0 9 0 \leq c_i\leq 10^9


Output

最短路径长度


Solution

$1.一种解决方法是多开一维记录状态,多开的维度记录状态的种类数即为分层数。 $
d i s t [ i ] [ j ] : i j i 使 j dist[i][j]:表示到达i点的第j层最短路径。也可以说到达i点使用了j次免费路径的最短路径。
d i s t [ n ] [ k ] 答案就是dist[n][k]
更新的时候除了对当前层的点松弛还要对下一层的点进行松弛。


Codes

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
struct Edge {
    int to;
    ll cost;
    Edge(){}
    Edge(int _t,ll _c) {to = _t;cost = _c;}
};
vector<Edge> ways[maxn];
struct qNode {
    int x,y;
    ll cost;
    qNode(){}
    qNode(int _t,int _k,ll _c) {x = _t;y = _k;cost = _c;}
    bool operator < (const qNode &a) const {
        return cost > a.cost;
    }
};
int n,m,k,from,to;
bool vis[maxn][15];
ll dist[maxn][15];
inline void init() {
    for(int i=0;i<maxn;i++) ways[i].clear();
}
inline void addedge(int u,int v,ll c) {
    ways[u].push_back(Edge(v,c));
}
ll solve(int from,int to) {
    memset(vis,0,sizeof(vis));
    memset(dist,0x3f,sizeof(dist));
    //printf("%lld\n",dist[0][0]);
    priority_queue<qNode> qu;
    while(!qu.empty()) qu.pop();
    dist[from][0] = 0;
    qu.push(qNode(from,0,dist[from][0]));
    qNode now;
    Edge tmp;
    while(!qu.empty()) {
        now = qu.top(); qu.pop();
        int u = now.x,step = now.y;
        vis[u][step] = true;
        for(int i=0;i<ways[u].size();i++) {
            tmp = ways[u][i];
            int v = tmp.to;ll cost = tmp.cost;
            if(!vis[v][step] && dist[v][step] > dist[u][step] + cost) {
                dist[v][step] = dist[u][step] + cost;
                qu.push(qNode(v,step,dist[v][step]));
            }
            /// 对下一层进行松弛
            if(step == k) continue;
            if(!vis[v][step+1] && dist[v][step+1] > dist[u][step]) {
                dist[v][step+1] = dist[u][step];
                qu.push(qNode(v,step+1,dist[v][step+1]));
            }
        }
    }
    return dist[to][k];
}
int main()
{
    int caset;scanf("%d",&caset);
    while(caset--) {
        scanf("%d%d%d",&n,&m,&k);
        init();
        // scanf("%d%d",&from,&to);
        ll c;
        for(int i=0,u,v;i<m;i++) {
            scanf("%d%d%lld",&u,&v,&c);
            addedge(u,v,c);
        }
        ll ans = solve(1,n);
        printf("%lld\n",ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38013346/article/details/82313662
今日推荐