代码编织梦想

1 介绍

本专题用来介绍使用最短路算法(spfa或dijkstra)与其它算法(dfs等等)结合起来解题。

2 训练

题目11135新年好

C++代码如下,

//版本1,使用vector来存储图,会有超时风险
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

const int N = 50010;
int n, m;
int dist[6][N];
bool st[N];
vector<vector<pair<int, int>>> g; //使用vector可能有超时分险
int source[6];

void spfa(int start, int dist[]) {
    memset(dist, 0x3f, N * 4);
    memset(st, 0, sizeof st);
    
    dist[start] = 0;
    queue<int> q;
    q.push(start);
    st[start] = true;
    
    while (!q.empty()) {
        auto t = q.front();
        q.pop();
        st[t] = false;
        
        for (auto [b, w] : g[t]) {
            if (dist[b] > dist[t] + w) {
                dist[b] = dist[t] + w;
                if (!st[b]) {
                    q.push(b);
                    st[b] = true;
                }
            }
        }
        
    }
    
    return;
}

int dfs(int u, int start, int distance) {
    if (u > 5) return distance;
    
    int res = 0x3f3f3f3f;
    for (int i = 1; i <= 5; ++i) {
        if (!st[i]) {
            int b = source[i];
            st[i] = true;
            res = min(res, dfs(u + 1, i, distance + dist[start][b]));
            st[i] = false; 
        }
    }
    return res;
}

int main() {
    cin >> n >> m;
    g.resize(n + 10);
    
    source[0] = 1;
    for (int i = 1; i <= 5; ++i) cin >> source[i];
    
    for (int i = 0; i < m; ++i) {
        int a, b, c;
        cin >> a >> b >> c;
        g[a].emplace_back(b, c);
        g[b].emplace_back(a, c);
    }
    
    for (int i = 0; i < 6; ++i) spfa(source[i], dist[i]);
    
    memset(st, 0, sizeof st);
    int res = dfs(1, 0, 0);
    
    cout << res << endl;
    
    return 0;   
}
//版本2,使用h,e,ne,w数组来存储图
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int, int> PII;

const int N = 50010, M = 200010, INF = 0x3f3f3f3f;

int n, m;
int h[N], e[M], w[M], ne[M], idx;
int q[N], dist[6][N];
int source[6];
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 dijkstra(int start, int dist[]) {
    memset(dist, 0x3f, N * 4);
    dist[start] = 0;
    memset(st, 0, sizeof st);
    
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, start});
    
    while (heap.size()) {
        auto t = heap.top();
        heap.pop();
        
        int ver = t.second;
        if (st[ver]) continue;
        st[ver] = true;
        
        for (int i = h[ver]; ~i; i = ne[i]) {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i]) {
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
}

int dfs(int u, int start, int distance) {
    if (u > 5) return distance;
    
    int res = INF;
    for (int i = 1; i <= 5; ++i) {
        if (!st[i]) {
            int next = source[i];
            st[i] = true;
            res = min(res, dfs(u + 1, i, distance + dist[start][next]));
            st[i] = false; 
        }
    }
    return res;
}

int main() {
    scanf("%d%d", &n, &m);
    source[0] = 1;
    for (int i = 1; i <= 5; ++i) scanf("%d", &source[i]);
    
    memset(h, -1, sizeof h);
    while (m--) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c), add(b, a, c);
    }
    
    for (int i = 0; i < 6; ++i) dijkstra(source[i], dist[i]);
    
    memset(st, 0, sizeof st);
    printf("%d\n", dfs(1, 0, 0));
    
    return 0;
}

题目2340通信线路

C++代码如下,

#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>

using namespace std;

const int N = 1010, M = 20010;
int n, m, k;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
deque<int> q;
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 check(int bound) {
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);
    
    q.push_back(1);
    dist[1] = 0;
    
    while (q.size()) {
        int t = q.front();
        q.pop_front();
        
        if (st[t]) continue;
        st[t] = true;
        
        for (int i = h[t]; ~i; i = ne[i]) {
            int j = e[i], x = w[i] > bound;
            if (dist[j] > dist[t] + x) {
                dist[j] = dist[t] + x;
                if (!x) q.push_front(j);
                else q.push_back(j);
            }
        }
    }
    return dist[n] <= k;
}

int main() {
    cin >> n >> m >> k;
    memset(h, -1, sizeof h);
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }
    
    int l = 0, r = 1e6 + 1;
    while (l < r) {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    
    if (r == 1e6 + 1) cout << -1 << endl;
    else cout << r << endl;
    
    return 0;
}

题目3

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/YMWM_/article/details/137158729

使用哈希表统计数组中数字出现的次数-爱代码爱编程

#include <iostream> #include <map> using namespace std; int main() { int array[11] = {1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5}; map<int, int, less&l

C++中如何查询map中是否存在某个元素-爱代码爱编程

//1 利用count #include <unordered_map> unordered_map<string, int> dist; dist.count(x) == 1;//x元素存在 dist.count(x) == 0;//x元素不存在 //2 利用find dist.find(x) != dist.end();//x元

std::thread介绍-爱代码爱编程

目录 创建线程成员函数使用不写`join()`或`detach()`报错mutex基本使用进阶参考   C++中的一个表示执行线程的类。一个执行线程是一个指令序列,它可以在多线程环境中与其它这样的序列同时执行,共享相同的地址空间。一个已经初始化了的线程对象表示正在执行的活动线程,这样的线程对象是joinable(可接合的,不知道翻译的对不对),并

牛客网输入输出11道题-爱代码爱编程

目录 第1题第2题第3题第4题第5题第6题第7题第8题第9题第10题第11题 第1题 输入描述: 输入包括两个正整数a,b(1 <= a, b <= 10^9),输入数据包括多组。 输出描述: 输出a+b的结果 输入例子1: 1 5 10 20 输出例子1: 6 30 我的代码 #include <

C++中计算迭代器之间的距离-爱代码爱编程

在C++中,我们经常会碰到,需要计算两个迭代器之间的距离,例如 set<string> myset;//集合myset中存了一些数 string str;//假定str一定在myset中,求取它的位置 迭代器1:myset.find(str) 迭代器2:myset.begin() 要计算迭代器1与迭代器2之间的距离,由于某些迭代器只支持+

c++代码库cppsqlite3使用技巧_sqlitecpp-爱代码爱编程

目录 1 常规使用2 查询和插入3 查询和更新 1 常规使用 (零) 头文件列表, #include "database.h" #include "query.h" #include "stat

acwing算法基础之搜索与图论-爱代码爱编程

目录 1 基础知识2 模板3 工程化 1 基础知识 kruskal算法的关键步骤为: 将所有边按照权重从小到大排序。定义集合S,表示生成树。枚举每条边(a,b,c),起点a,终点b,边长c。如果结