道路与航线

道路与航线

\(topsort + dijkstra\)

\(有负边,但spfa已死.\)

\(由题意,图中会有很多块,每个块之间是航路(单向边),块内部是道路(双向边).\\所以我们用拓扑序的顺序对每个块做Djk就可以了.保证了正确性和时间.\)

#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PII pair<int, int>
#define VIT vector<int>
#define x first
#define y second
#define inf 0x3f3f3f3f
const int N = 25010, M = 150010;
int h[N], ne[M], w[M], e[M], idx;
int d[N];
bool st[N];
int n, m1, m2, S;
int id[N], cnt;
int din[N];
vector<int> blo[N];
queue<int> q;

void add(int a, int b, int c) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void dfs(int u, int bid) {
    id[u] = bid;
    blo[bid].pb(u);
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!id[j]) dfs(j, bid);
    }
}


void show_block() {
    cout << cnt << '\n';
    for (int i = 1; i <= cnt; ++i) {
        for (int j : blo[i]) cout << j << ' ';
        cout << '\n';
    }
}

void dijkstra(int bid) {
    priority_queue<PII, vector<PII>, greater<PII>> pq;
    for (auto i : blo[bid]) pq.push({d[i], i});
    while (pq.size()) {
        PII t = pq.top();
        pq.pop();
        int ver = t.y, dis = t.x;
        if (st[ver]) continue;
        st[ver] = 1;
        for (int i = h[ver]; ~i; i = ne[i]) {
            int j = e[i];
            if (id[j] != id[ver] && --din[id[j]] == 0) q.push(id[j]);
            if (d[j] > dis + w[i]) {
                d[j] = dis + w[i];
                if (id[j] == id[ver]) pq.push({d[j], j});
            }
        }
    }
}

void topsort() {
    memset(d, 0x3f, sizeof d);
    d[S] = 0;
    for (int i = 1; i <= cnt; ++i) 
        if (!din[i]) q.push(i);
    while (q.size()) {
        int t = q.front();
        q.pop();
        dijkstra(t);
    }
}

int main() {
    IO;
    //freopen("in.txt", "r", stdin);
    memset(h, -1, sizeof h);
    cin >> n >> m1 >> m2 >> S;
    while (m1--) {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }

    for (int i = 1; i <= n; ++i) 
        if (!id[i]) dfs(i, ++cnt);

    while (m2--) {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
        din[id[b]]++;
    }

    topsort();
    for (int i = 1; i <= n; ++i)
        if (d[i] > inf / 2) cout << "NO PATH\n";
        else cout << d[i] << '\n';
    return 0;
}

posted @ 2021-03-23 22:07  phr2000  阅读(37)  评论(0编辑  收藏  举报