基础算法——搜索与图论

搜索与图论

图的存储方式

2、最短路问题

最短路问题可以分为单源最短路问题和多源最短路问题,单源最短路问题就是求出从点1->n的最短距离,而多源最短路问题就是求出从点i->j的最短距离。单源最短路问题还可以分为正权边的单源最短路问题和负权边的单源最短路问题。具体算法和时间复杂度如下图:

2.1、Dijkstra算法(朴素版)


算法模板:

cpp 复制代码
#include <iostream>
#include <cstring>

using namespace std;
const int N = 510;
int g[N][N], d[N];
int n, m;
bool st[N];

int dijkstra()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    for (int i = 0; i < n; i++)
    {
        int t = -1;
        for (int j = 1; j <= n; j++)
            if (!st[j] && (t == -1 || d[t] > d[j]))
                t = j;
        st[t] = true;
        for (int j = 1; j <= n; j++)
            d[j] = min(d[j], d[t] + g[t][j]);
    }
    return d[n] == 0x3f3f3f3f ? -1 : d[n];
}

int main()
{
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);
    while (m--)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = min(g[a][b], c);
    }
    cout << dijkstra() << endl;
    return 0;
}

2.2、Dijkstra算法(堆优化版)

下面来看看如何优化:

算法模板:

cpp 复制代码
#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
typedef pair<int, int> PII;
const int N = 1.5e5+10;
int h[N], e[N], w[N], ne[N], idx;
int n, m, d[N];
bool st[N];

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

int dijkstra()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});
    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();
        int ver = t.second, dis = t.first;
        if (st[ver]) continue;
        st[ver] = true;
        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (d[j] > dis + w[i])
            {
                d[j] = dis + w[i];
                heap.push({d[j], j});
            }
        }
    }
    return d[n] == 0x3f3f3f3f ? -1 : d[n];
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    while (m--)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    cout << dijkstra() << endl;
    return 0;
}

2.3、Bellman-Ford算法


代码模板:

cpp 复制代码
#include <iostream>
#include <cstring>

using namespace std;
const int N = 510, M = 10010;
int n, m, k;
int d[N], backup[N];

struct Edge
{
    int a, b, w;
}edges[M];

void bellman_ford()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    for (int i = 0; i < k; i++)
    {
        memcpy(backup, d, sizeof d);
        for (int j = 0; j < m; j++)
        {
            auto e = edges[j];
            d[e.b] = min(d[e.b], backup[e.a] + e.w);
        }
    }
}

int main()
{
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++)
    {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }
    bellman_ford();
    if (d[n] > 0x3f3f3f3f / 2) cout << "impossible" << endl;
    else cout << d[n] << endl;
    return 0;
}

2.4、SPFA求最短路

代码模板:

cpp 复制代码
#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
const int N = 1e5+10;
int n, m;
int h[N], e[N], w[N], ne[N], idx;
int d[N];
bool st[N];

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

void spfa()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    queue<int> q;
    q.push(1);
    st[1] = true;
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        st[t] = false;
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (d[j] > d[t] + w[i])
            {
                d[j] = d[t] + w[i];
                if (!st[j])
                {
                    st[j] = true;
                    q.push(j);
                }
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    while (m--)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    spfa();
    if (d[n] == 0x3f3f3f3f) cout << "impossible" << endl;
    else cout << d[n] << endl;
    return 0;
}

2.5、SPFA判负环

cpp 复制代码
#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
const int N = 2010, M = 10010;
int h[N], e[M], w[M], ne[M], idx;
int n, m;
int d[N], cnt[N];
bool st[N];

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

bool spfa()
{
    queue<int> q;
    for (int i = 1; i <= n; i++)
    {
        q.push(i);
        st[i] = true;
    }
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        st[t] = false;
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (d[j] > d[t] + w[i])
            {
                d[j] = d[t] + w[i];
                cnt[j] = cnt[t] + 1;
                if (cnt[j] >= n) return true;
                if (!st[j])
                {
                    st[j] = true;
                    q.push(j);
                }
            }
        }
    }
    return false;
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    while (m--)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    if (spfa()) cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}

2.6、Floyd算法

cpp 复制代码
#include <iostream>
#include <cstring>

using namespace std;
const int N = 210, INF = 0x3f3f3f3f;
int d[N][N];
int n, m, k;

void floyd()
{
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

int main()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (i == j) d[i][j] = 0;
            else d[i][j] = INF;
    while (m--)
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = min(d[a][b], c);
    }
    floyd();
    while (k--)
    {
        int l, r;
        cin >> l >> r;
        if (d[l][r] > INF / 2) cout << "impossible" << endl;
        else cout << d[l][r] << endl;
    }
    return 0;
}
相关推荐
CodeWithMe24 分钟前
【Algorithm】图论入门
c++·图论
CQ_07124 小时前
自学记录:力扣hot100第三题
算法·leetcode
Wilber的技术分享7 小时前
【机器学习实战笔记 12】集成学习:AdaBoost算法
人工智能·笔记·算法·决策树·机器学习·分类·集成学习
金融小师妹8 小时前
基于LSTM-GARCH混合模型的“获利了结”量化解析:黄金单日1.27%跌幅的技术性归因
大数据·人工智能·算法
不良手残9 小时前
Java实现10大经典排序算法
数据结构·算法·排序算法
是紫焅呢9 小时前
I排序算法.go
开发语言·后端·算法·golang·排序算法·学习方法·visual studio code
辉辉还没睡10 小时前
Lora训练
人工智能·算法·机器学习
电院大学僧12 小时前
初学python的我开始Leetcode题10-2
python·算法·leetcode
码破苍穹ovo13 小时前
二分查找----1.搜索插入位置
数据结构·算法
烨然若神人~14 小时前
算法第38天|322.零钱兑换\139. 单词拆分
算法