1. 程式人生 > 其它 >[圖論]分層圖最短路

[圖論]分層圖最短路

技術標籤:圖論

ABC132 – E – Hopscotch Addict
https://atcoder.jp/contests/abc132/tasks/abc132_e
分層圖的思想很重要。
這題算比較簡單的,因為每次都要走三步,我們假設每次只走一步,那麼每個點就有三種狀態:起點(終點)、走一步到達的點、走兩步到達的點,那麼我們把圖分成三層,每走一步相當於往下一層圖走,只有每三步到達的點才是最終停下來的點,連邊的時候就連到下一層對應的點,這個方法同時也能很好的處理環的情況,建完圖bfs一下就好了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int maxn = 1e5 + 5, inf = 0x3f3f3f3f; vector<int> g[3 * maxn]; int d[3 * maxn]; int main() { ios::sync_with_stdio(0); cin.tie(0); int n, m; cin >> n >> m; while (m--){ int u, v; cin >> u >> v; //模3迴圈,點分成3層,模3為0的u連到模3為1的v,後面同理
g[3 * u].push_back(3 * v + 1); g[3 * u + 1].push_back(3 * v + 2); g[3 * u + 2].push_back(3 * v); } int s, t; cin >> s >> t; queue<int> qi; qi.push(3 * s); while (!qi.empty()){ int u = qi.front(); qi.pop(); for (int v :
g[u]) if (!d[v]) { d[v] = d[u] + 1; qi.push(v); } } cout << (d[3 * t] ? d[3 * t] / 3 : -1) << endl; return 0; }

洛谷 – P4568 – [JLOI2011]飛行路線
https://www.luogu.org/problem/P4568

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int maxn = 1e5 + 1e4 + 10;
struct edge{
    int v, c;
};
vector<edge> g[maxn];
int d[maxn];
int main()
{
    int n, m, k, q, z, u, v, c;
    scanf("%d %d %d %d %d", &n, &m, &k, &q, &z);
    ++k;//多搞一層
    for (int i = 1; i <= m; ++i){
        scanf("%d %d %d", &u, &v, &c);
        for (int j = 0; j < k; ++j){
            if (j < k - 1) g[k * u + j].emplace_back(edge{k * v + j + 1, 0});
            if (j < k - 1) g[k * v + j].emplace_back(edge{k * u + j + 1, 0});
            g[k * u + j].emplace_back(edge{k * v + j, c});
            g[k * v + j].emplace_back(edge{k * u + j, c});
        }
    }
    memset(d, 0x3f, sizeof(d));
    d[k * q] = 0;
    priority_queue<pii, vector<pii>, greater<pii> > pqi;
    pqi.push(pii(0, k * q));
    while(!pqi.empty()){
        pii e = pqi.top(); pqi.pop();
        if (d[e.second] < e.first) continue;
        int u = e.second, c = e.first;
        for (edge te : g[u]){
            if (d[te.v] > c + te.c){
                d[te.v] = c + te.c;
                pqi.push(pii(d[te.v], te.v));
            }
        }
    }
    int ans = inf;
    for (int i = 0; i < k; ++i) ans = min(ans, d[z * k + i]);
    printf("%d\n", ans);
    return 0;
}