[A through study notes] Shortest Path

Dijkstra shortest path algorithm commonly used and SPFA. SPFA support negative weights, but likely to be cancer data card.
SPFA want to run quickly join a small optimization: instead of using deque queue, and then classify the Push of time, if it is smaller than the current front Push Front of dis, otherwise Push Back.
Shortest time count and short problem can be modeled ordinary DP process. Short-circuits in strict strict attention to non-discrimination.
The main consideration of common modeling techniques layered maps. Possibly in combination with dichotomous answers when dealing with real problems or enumeration carried out.

10074. "3.2 cases through a 3" to set up a telephone line

#include <bits/stdc++.h>
using namespace std;
const int MAX_NODE = 100005;
const int MAX_EDGE = 1000005;
template <class T>
class Graph_SP {  // 解决单源最短路径问题
public:
    vector<pair<int, T> > G[MAX_NODE];
    int d[MAX_NODE], v[MAX_NODE], f[MAX_NODE];
    T t[MAX_NODE];                     // 距离表与访问标识表
    void make(int t1, int t2, T t3) {  // 造边(有向)
        G[t1].push_back(make_pair(t2, t3));
    }
    void reset_graph(int n) {  // 用于清除图邻接表
        for (int i = 0; i <= n; i++) G[i].clear();
    }
    void reset_solver(int n) {  // 对距离表与访问标识表的清除 如果改变了类型,该函数可能需要重写!
        memset(d, 0x3f, sizeof d);
        memset(v, 0x00, sizeof v);
        memset(f, 0x00, sizeof f);
    }
    void solveSPFA(int v0, int n) {  // 执行主计算任务(使用SPFA)
        queue<int> q;
        reset_solver(n);  // 自动调用对距离表与访问标识表的清除
        // d[0]=0;
        d[v0] = 0;
        v[v0] = 1;
        q.push(v0);
        while (q.size()) {
            int p = q.front();
            q.pop();
            v[p] = 0;
            for (int i = 0; i < G[p].size(); i++) {
                int x = G[p][i].first;  // x为当前枚举边的终点,
                T y = G[p][i].second;   // y为当前枚举边的权值
                if (d[x] > d[p] + y) {
                    d[x] = d[p] + y;
                    t[x] = y;
                    f[x] = p;
                    if (!v[x])
                        q.push(x);
                }
            }
        }
    }
};
Graph_SP<int> g;
int n, m, k;
struct Edge {
    int u, v, w;
    bool operator<(const Edge &b) { return w < b.w; }
} e[MAX_EDGE];
int check(int lim) {
    g.reset_graph(n);
    for (int i = 1; i <= m; i++) {
        g.make(e[i].u, e[i].v, (e[i].w > lim));
        g.make(e[i].v, e[i].u, (e[i].w > lim));
    }
    g.solveSPFA(1, n);
    return g.d[n];
}
int main() {
    cin >> n >> m >> k;
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        e[i].u = u;
        e[i].v = v;
        e[i].w = w;
    }
    sort(e + 1, e + m + 1);
    int l = 0, r = 1e+9;
    while (r > l) {
        int mid = (l + r) >> 1;
        if (check(mid) > k)
            l = mid + 1;
        else
            r = mid;
    }
    cout << (l >= 1e+9 ? -1 : l) << endl;
}

10075. "one through 3.2 Exercise 1" farm party

#include <bits/stdc++.h>
using namespace std;

const int MAX_NODE = 100005;
const int MAX_EDGE = 200005;

template <class T>
class Graph_SP {  // 解决单源最短路径问题
public:
    vector<pair<int, T> > G[MAX_NODE];
    int d[MAX_NODE], v[MAX_NODE];           // 距离表与访问标识表
    void make_edge(int t1, int t2, T t3) {  // 造边(有向)
        G[t1].push_back(make_pair(t2, t3));
    }
    void reset_graph(int n) {  // 用于清除图邻接表
        for (int i = 0; i <= n; i++) G[i].clear();
    }
    void reset_solver(int n) {  // 对距离表与访问标识表的清除 如果改变了类型,该函数可能需要重写!
        memset(d, 0x3f, sizeof d);
        memset(v, 0x00, sizeof v);
    }
    void solveSPFA(int v0, int n) {  // 执行主计算任务(使用SPFA)
        queue<int> q;
        reset_solver(n);  // 自动调用对距离表与访问标识表的清除
        d[v0] = 0;
        v[v0] = 1;
        q.push(v0);
        while (q.size()) {
            int p = q.front();
            q.pop();
            v[p] = 0;
            for (int i = 0; i < G[p].size(); i++) {
                int x = G[p][i].first;  // x为当前枚举边的终点,
                T y = G[p][i].second;   // y为当前枚举边的权值
                if (d[x] > d[p] + y) {
                    d[x] = d[p] + y;
                    if (!v[x])
                        q.push(x);
                }
            }
        }
    }
};
Graph_SP<int> g1, g2;
int n, m, x, u, v, w;

int main() {
    cin >> n >> m >> x;
    for (int i = 1; i <= m; i++) {
        cin >> u >> v >> w;
        g1.make_edge(u, v, w);
        g2.make_edge(v, u, w);
    }
    g1.solveSPFA(x, n);
    g2.solveSPFA(x, n);
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = max(ans, g1.d[i] + g2.d[i]);
    }
    cout << ans << endl;
}

10076. "one through 3.2 Exercise 2" Roadblocks

#include <bits/stdc++.h>
using namespace std;
const int MAX_NODE = 5005;
const int MAX_EDGE = 200005;
template <class T>
class Graph_SP {  // 解决单源最短路径问题
public:
    vector<pair<int, T> > G[MAX_NODE];
    int d[MAX_NODE], v[MAX_NODE], s[MAX_NODE];  // 距离表与访问标识表
    void make_edge(int t1, int t2, T t3) {      // 造边(有向)
        G[t1].push_back(make_pair(t2, t3));
    }
    void reset_graph(int n) {  // 用于清除图邻接表
        for (int i = 0; i <= n; i++) G[i].clear();
    }
    void reset_solver(int n) {  // 对距离表与访问标识表的清除 如果改变了类型,该函数可能需要重写!
        memset(d, 0x3f, sizeof d);
        memset(s, 0x3f, sizeof d);
        memset(v, 0x00, sizeof v);
    }
    void solveSPFA(int v0, int n) {  // 执行主计算任务(使用SPFA)
        queue<int> q;
        reset_solver(n);  // 自动调用对距离表与访问标识表的清除
        d[v0] = 0;
        v[v0] = 1;
        q.push(v0);
        while (q.size()) {
            int p = q.front();
            q.pop();
            v[p] = 0;
            for (int i = 0; i < G[p].size(); i++) {
                int x = G[p][i].first;  // x为当前枚举边的终点,
                T y = G[p][i].second;   // y为当前枚举边的权值
                if (d[x] > d[p] + y) {
                    s[x] = d[x];
                    d[x] = d[p] + y;
                    if (!v[x])
                        q.push(x), v[x] = 1;
                }
                if (s[x] > d[p] + y && d[p] + y != d[x]) {
                    s[x] = d[p] + y;
                    if (!v[x])
                        q.push(x), v[x] = 1;
                }
                if (s[x] > s[p] + y && s[p] + y != d[x]) {
                    s[x] = s[p] + y;
                    if (!v[x])
                        q.push(x), v[x] = 1;
                }
            }
        }
    }
};
Graph_SP<int> g;
int n, m, u, v, w;

int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> u >> v >> w;
        g.make_edge(u, v, w);
        g.make_edge(v, u, w);
    }
    g.solveSPFA(1, n);
    cout << g.s[n] << endl;
}

10078. "one through 3.2 Exercise 4" Happy New Year

#include <bits/stdc++.h>
using namespace std;
const int MAX_NODE = 100005;
const int MAX_EDGE = 1000005;
template <class T>
class Graph_SP {  // 解决单源最短路径问题
public:
    vector<pair<int, T> > G[MAX_NODE];
    int d[MAX_NODE], v[MAX_NODE];           // 距离表与访问标识表
    void make_edge(int t1, int t2, T t3) {  // 造边(有向)
        G[t1].push_back(make_pair(t2, t3));
    }
    void reset_graph(int n) {  // 用于清除图邻接表
        for (int i = 0; i <= n; i++) G[i].clear();
    }
    void reset_solver(int n) {  // 对距离表与访问标识表的清除 如果改变了类型,该函数可能需要重写!
        memset(d, 0x3f, sizeof d);
        memset(v, 0x00, sizeof v);
    }
    void solveSPFA(int v0, int n) {  // 执行主计算任务(使用SPFA)
        queue<int> q;
        reset_solver(n);  // 自动调用对距离表与访问标识表的清除
        d[v0] = 0;
        v[v0] = 1;
        q.push(v0);
        while (q.size()) {
            int p = q.front();
            q.pop();
            v[p] = 0;
            for (int i = 0; i < G[p].size(); i++) {
                int x = G[p][i].first;  // x为当前枚举边的终点,
                T y = G[p][i].second;   // y为当前枚举边的权值
                if (d[x] > d[p] + y) {
                    d[x] = d[p] + y;
                    if (!v[x])
                        q.push(x), v[x] = 1;
                }
            }
        }
    }
};

Graph_SP<int> g[6];
int n, m, p[6], u, v, w;
int perm[6] = { 0, 1, 2, 3, 4, 5 };

int main() {
    cin >> n >> m >> p[1] >> p[2] >> p[3] >> p[4] >> p[5];
    p[0] = 1;
    for (int i = 1; i <= m; i++) {
        cin >> u >> v >> w;
        for (int j = 0; j < 6; j++) g[j].make_edge(u, v, w), g[j].make_edge(v, u, w);
    }
    for (int i = 0; i < 6; i++) {
        g[i].solveSPFA(p[i], n);
    }
    int ans = 1e+9;
    while (next_permutation(perm + 1, perm + 6)) {
        int sum = 0;
        for (int i = 1; i < 6; i++) sum += g[perm[i - 1]].d[p[perm[i]]];
        ans = min(ans, sum);
    }
    cout << ans << endl;
}

10081. "one through 3.2 Exercise 7" road and route

#include <bits/stdc++.h>
using namespace std;

const int MAX_NODE = 100005;
const int MAX_EDGE = 1000005;
template <class T>
class Graph_SP {  // 解决单源最短路径问题
public:
    vector<pair<int, T> > G[MAX_NODE];
    int d[MAX_NODE], v[MAX_NODE];           // 距离表与访问标识表
    void make_edge(int t1, int t2, T t3) {  // 造边(有向)
        G[t1].push_back(make_pair(t2, t3));
    }
    void reset_graph(int n) {  // 用于清除图邻接表
        for (int i = 0; i <= n; i++) G[i].clear();
    }
    void reset_solver(int n) {  // 对距离表与访问标识表的清除 如果改变了类型,该函数可能需要重写!
        memset(d, 0x3f, sizeof d);
        memset(v, 0x00, sizeof v);
    }
    void solveSPFA(int v0, int n) {  // 执行主计算任务(使用SPFA)
        deque<int> q;
        reset_solver(n);  // 自动调用对距离表与访问标识表的清除
        d[v0] = 0;
        v[v0] = 1;
        q.push_front(v0);
        while (q.size()) {
            int p = q.front();
            q.pop_front();
            v[p] = 0;
            for (int i = 0; i < G[p].size(); i++) {
                int x = G[p][i].first;  // x为当前枚举边的终点,
                T y = G[p][i].second;   // y为当前枚举边的权值
                if (d[x] > d[p] + y) {
                    d[x] = d[p] + y;
                    if (!v[x]) {
                        v[x] = 1;
                        if (!q.empty() && d[x] < d[q.front()])
                            q.push_front(x);
                        else
                            q.push_back(x);
                    }
                }
            }
        }
    }
};

int n, m, p, s, u, v, w;
Graph_SP<int> g;

int main() {
    ios::sync_with_stdio(false);
    cin >> n >> m >> p >> s;
    for (int i = 1; i <= m; i++) {
        cin >> u >> v >> w;
        g.make_edge(u, v, w);
        g.make_edge(v, u, w);
    }
    for (int i = 1; i <= p; i++) {
        cin >> u >> v >> w;
        g.make_edge(u, v, w);
    }
    g.solveSPFA(s, n);
    for (int i = 1; i <= n; i++) {
        if (g.d[i] >= 0x3f3f3f3f)
            cout << "NO PATH" << endl;
        else
            cout << g.d[i] << endl;
    }
}

Guess you like

Origin www.cnblogs.com/mollnn/p/11615611.html