BZOJ2763: [JLOI2011]飛行路線(分層圖 最短路)

自為風月馬前卒發表於2018-11-09

題意

題目連結

Sol

分層圖+最短路

(k+1)層圖,對於邊((u, v, w)),首先在本層內連邊權為(w)的無向邊,再各向下一層對應的節點連邊權為(0)的有向邊

如果是取最大最小值的話可以考慮二分答案+最短路

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP make_pair 
#define fi first
#define se second 
using namespace std;
const int MAXN = 2e5 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < `0` || c > `9`) {if(c == `-`) f = -1; c = getchar();}
    while(c >= `0` && c <= `9`) x = x * 10 + c - `0`, c = getchar();
    return x * f;
}
int N, M, K, S, T, TT, vis[MAXN], dis[MAXN];
vector<Pair> v[MAXN];
void AddEdge(int x, int y, int z, int f) {
    v[x].push_back(MP(y, z));
    if(f) v[y].push_back(MP(x, z));
}
void Dij(int s) {
    priority_queue<Pair> q; q.push(MP(0, s));
    memset(dis, 0x3f, sizeof(dis)); dis[s] = 0;
    while(!q.empty()) {
        if(vis[q.top().se]) {q.pop(); continue;}
        int p = q.top().se; q.pop(); vis[p] = 1;
        for(int i = 0; i < v[p].size(); i++) {
            int to = v[p][i].fi, w = v[p][i].se;
            if(dis[to] > dis[p] + w) dis[to] = dis[p] + w, q.push(MP(-dis[to], to));
        }
    }
}
int main() {
//  freopen("a.in", "r", stdin);
    N = read(); M = read(); K = read(); S = read() + 1; T = read() + 1; TT = N * (K + 1) + 1;
    for(int i = 1; i <= M; i++) {
        int u = read() + 1, v = read() + 1, w = read();
        for(int j = 0; j < K; j++) {
            AddEdge(j * N + u, j * N + v, w, 1);
            AddEdge(j * N + u, (j + 1) * N + v, 0, 0);
            AddEdge(j * N + v, (j + 1) * N + u, 0, 0);
        }
        AddEdge(N * K + u, N * K + v, w, 1);
    }
    for(int j = 0; j <= K; j++) AddEdge(j * N + T, TT, 0, 0);
    Dij(S);
    printf("%d", dis[TT]);
    return 0;
}

相關文章