当前位置: 首页 > news >正文

最短路径题目练习

目录

一、蓝桥公园 1121-floyd算法

        题目描述

        完整代码 (滚动数组优化后的)

二、蓝桥王国1122-dijkstra算法

        题目描述

        完整代码

三、最短路问题3828- floyd算法

        题目描述

        完整代码

四、慈善晚会3035-dijkstra算法

        题目描述

        完整代码


往期参考文章链接,看这个就好啦:

图论--最短路问题总结-CSDN博客

一、蓝桥公园 1121-floyd算法

        题目描述

        完整代码 (滚动数组优化后的)

#include<bits/stdc++.h>
using namespace std;
const long long INF = 1e18;

int main() {
    int n, m, q;
    cin >> n >> m >> q;
    vector<vector<long long>> dist(n+1, vector<long long>(n+1, INF));
    
    // 初始化:自己到自己是0
    for(int i=1; i<=n; i++) dist[i][i] = 0;
    
    // 处理输入,保留最小边
    while(m--) {
        int u, v, w;
        cin >> u >> v >> w;
        if(w < dist[u][v]) {  // 处理重边
            dist[u][v] = w;
            dist[v][u] = w;  // 无向图
        }
    }
    
    // Floyd核心
    for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    
    // 处理查询
    while(q--) {
        int st, ed;
        cin >> st >> ed;
        if(dist[st][ed] == INF) cout << -1 << endl;
        else cout << dist[st][ed] << endl;
    }
    return 0;
}

二、蓝桥王国1122-dijkstra算法

        题目描述

    

     

        完整代码

//dijkstra
/*
1. 输入处理:读取节点数n和边数m,构建邻接表。

2. 初始化距离数组mindis,起点(节点1)的距离设为0,其他为LLONG_MAX。

3. 使用优先队列(小根堆)来存储当前的最短距离和节点。

4. 进入主循环,每次取出堆顶元素,进行松弛操作。

5. 松弛过程中更新相邻节点的最短距离,并将新的距离压入堆中。

6. 在每次处理完当前节点后,输出所有节点的当前最短距离。
*/
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n,m;
  cin>>n>>m;
  //邻接表存储图 u{v,w}
  vector<vector<pair<int ,int>>> grid(n+1);
  //存储图,m条边
  for(int i=0;i<m;i++)
  {
    int u,v,w;
    cin>>u>>v>>w;
    grid[u].emplace_back(v,w); //单向边 ,无重边
  }
  //初始化距离数组
  vector<ll> mindis(n+1,LLONG_MAX);
  mindis[1]=0;
  //小根堆:每次弹出数值最小的 
  priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<>> pq; //每次弹出当前节点与相邻节点的最短路径
  pq.emplace(0,1);//距离,结点
  //算法
  while(!pq.empty())
  {
    auto [dis,cur] = pq.top();
    pq.pop();
    if(mindis[cur]>dis) continue;
    //松弛:遍历从cur 出发的所有点
    for(auto [v,w] : grid[cur])
    {
      if(mindis[cur]+w<mindis[v])
      {
        mindis[v]=mindis[cur]+w;
        //将新的最短距离压入队列
        pq.emplace(mindis[v],v);
      }
    }
   
  }
   //输出最短路径的距离
    for(int i=1;i<=n;i++)
    {
      if (i > 1) cout << " ";
      if(mindis[i]==LLONG_MAX) cout<<"-1";
      else cout<<mindis[i];
    }

return 0;

}

此题邻接表优化空间n=3e5时,邻接矩阵需要3e5×3e5=9e10个元素的存储空间,按每个元素8字节(long long)计算,总内存需求约为720,000 GB,远超任何合理内存限制大规模稀疏图

还要将朴素的O(N²)搜索改为优先队列优化

使用邻接矩阵存储的代码

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

#define INF INT_MAX

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    // 初始化图,默认所有路径为INT_MAX(表示无穷大)
    vector<vector<pair<int, int>>> adj(n + 1);  // adj[u] 存储 (v, w) 表示从 u 到 v 权重为 w

    // 输入图的边
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        adj[u].push_back({v, w});
    }

    // 初始化最短距离数组
    vector<int> mindist(n + 1, INF);
    mindist[1] = 0;

    // 使用优先队列 (min-heap),存储 {距离, 节点}
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    pq.push({0, 1});  // 从节点 1 开始,距离为 0

    // Dijkstra 算法
    while (!pq.empty()) {
        int u = pq.top().second;
        int dist_u = pq.top().first;
        pq.pop();

        // 如果当前节点的最短距离已经被访问过,跳过
        if (dist_u > mindist[u]) continue;

        // 更新与当前节点相邻的节点的最短距离
        for (auto& edge : adj[u]) {
            int v = edge.first;
            int weight = edge.second;

            if (mindist[u] + weight < mindist[v]) {
                mindist[v] = mindist[u] + weight;
                pq.push({mindist[v], v});
            }
        }
    }

    // 输出结果
    for (int i = 1; i <= n; i++) {
        if (mindist[i] == INF) {
            cout << "-1 ";
        } else {
            cout << mindist[i] << " ";
        }
    }

    return 0;
}

but:..........

三、最短路问题3828- floyd算法

        题目描述

        完整代码

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;

//求最大公因数
int gcd(int a,int b)
{
  return (b==0)?a:gcd(b,a%b);
}
//求最小公倍数
int lcm(int a,int b)
{
  return  a/gcd(a,b)*b;
}

//质数
bool iszhishu(int x)
{
  if(x==1) return false;//1不是质数
  if(x==2) return true;//2是唯一的偶质数
  if (x % 2 == 0) return false; // 排除其他偶数
  for(int i=3;i<=sqrt(x);i+=2) /// 从3开始,每次加2(跳过偶数)
  {
    if(x%i==0) return false; //发现因数,不是质数

  }
  return true;// 没有因数
}

int main() {
    int n, q;
    cin >> n >> q;

    // 初始化所有点对的邻接矩阵,权值为INF
    vector<vector<int>> dist(n+1, vector<int>(n+1, INF));
    
    // 构建边
    for (int i = 1; i <= n; ++i) {
        for (int j = i+1; j <= n; ++j) {  // 保证i < j,满足第一个条件
            bool a = iszhishu(i), b = iszhishu(j);
            if ((a && !b) || (!a && b)) { // 恰好一个质数,满足第二个条件
                dist[i][j] = lcm(i, j);   // 单向边i->j,权值为最小公倍数
            }
        }
    }

    // Floyd算法核心
   for(int k=1;k<=n;k++)
   {
     for(int i=1;i<=n;i++)
     {
       for(int j=1;j<=n;j++)
       {
         dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
       }
     }
   }

    // 处理q个查询
    while (q--) {
        int a, b;
        cin >> a >> b;
        if (dist[a][b] == INF) cout << -1 << endl;
        else cout << dist[a][b] << endl;
    }

    return 0;
}

结合了一点数学思维。。。 掌握了求最大公因数、最小公倍数、判断质数的数学知识,自己没想到的点是使用Floyd算法一次性计算所有点对之间的最短路径!!(因为所有点都是在n以内的 i<n  j<n)最后直接查询即可(还是太年轻啊.......)

四、慈善晚会3035-dijkstra算法

        题目描述

        完整代码

/*
题目大意:
n个节点,m条边(有重边、单向边),起点为p,不可达至为INF,
输出 该结点-->起始点 + 起始点-->该结点  来回的最大cost 【能去不一定能回.....需要存储正反图】
max( 到达某节点的最短路径 + 从该节点返回 p 的最短路径 )
*/

/*
解题思路:
1. 使用 Dijkstra 算法计算单源最短路径:
   -  `dis1` 存储从 p 到所有节点的最短路径。
   -  `dis2` 存储从所有节点返回到 p 的最短路径。
   -   因为是单向边所以需要构造**正向图和反向图**。
   
2. 计算最大往返代价:
   - 遍历所有节点,计算 `dis1[i] + dis2[i]`,取最大值。
   - 若节点不可达,则路径长度视为 INF
*/
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll INF = 1061109567;

void Dijkstra(int p, vector<ll>& mindist, vector<vector<pair<int,int>>>& adj) {
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;
    mindist[p] = 0;
    pq.push({0, p}); // 优先队列存储 (距离, 节点)
    
    while (!pq.empty()) {
        auto [dist,cur] = pq.top(); pq.pop();
        if (dist > mindist[cur]) continue; // 如果当前路径大于已知最短路径,则跳过
        
        for (auto [v,w] : adj[cur]) {
            if (mindist[v] > mindist[cur] + w) { // 松弛操作
                mindist[v] = mindist[cur] + w;
                pq.push({ mindist[v],v});
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(0);cin.tie(0);
    int n, m, p;
    cin >> n >> m >> p;
   vector<vector<pair<int,int>>> e1(n+1),e2(n+1); // 存储正向图与反向图
    vector<ll> dis1(n + 1, INF), dis2(n + 1, INF);// 初始化最短路径为 INF
    
    while(m--) {
        int u, v, w;
        cin >> u >> v >> w;
        e1[u].push_back({v, w}); // 正向图 
        e2[v].push_back({u, w}); // 反向图 
    }
    
    Dijkstra(p, dis1, e1);
    Dijkstra(p, dis2, e2);
    
    ll res = 0;
    for (int i = 1; i <= n; i++) { 
        ll to_i = (dis1[i] == INF ? INF : dis1[i]); // p → i
        ll from_i = (dis2[i] == INF ? INF : dis2[i]); // i → p
        res = max(res, to_i + from_i); // 计算最大往返路径
    }
    
    cout << res << endl;
    return 0;
}

第一次做到需要用到正反图的........自己真的考虑不到这个点(可能我很chun)

 

相关文章:

  • 内核、进程和线程---操作系统
  • Audacity Nyquist插件开发:插件标头详解
  • pnpm node_modules 高效删除
  • BAPLIE船图文件:EDI 核心字段与应用场景解析
  • 一维码与二维码的全面区别及选择指南:详解优劣势与应用
  • HCIP VRRP MSTP 交换综合实验
  • 小测验——合并多个网格文件调用相机参数进行适配
  • Baklib企业CMS的核心组成是什么?
  • 第J8周:Inception v1算法实战与解析
  • 【强化学习】基于深度强化学习的微能源网能量管理与优化策略研究【Python】
  • 2019 CCF CSP-S2.Emiya 家今天的饭
  • [识记]Mysql8 远程授权
  • Spring Boot 实战:MD5 密码加密应用全解析
  • Docker Desktop 界面功能介绍
  • Numpy用法(二)
  • 大语言模型(LLM)应用开篇 | RAG方法论概述 | 构建知识库探索
  • 【环路补偿】环路补偿的九种类型-mathcad计算书免费下载
  • 怎么对asp.web api进行单元测试?
  • LLM模型微调方法
  • 高压NPN
  • 公示资费套餐、规范营销行为,今年信息通信行业将办好这十件实事
  • 福州一宋代古墓被指沦为露天厕所,仓山区博物馆:已设置围挡
  • 嫩黑线货物列车脱轨致1名路外人员死亡,3人被采取刑事强制措施
  • 国寿资产获批参与第三批保险资金长期投资改革试点
  • 关税互降后的外贸企业:之前暂停的订单加紧发货,后续订单考验沟通谈判能力
  • 张国清将赴俄罗斯举行中俄“长江—伏尔加河”地方合作理事会第五次会议和“东北—远东”政府间合作委员会双方主席会晤