校园网站建立西安网站seo工作室
目录
一、蓝桥公园 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));// 初始化:自己到自己是0for(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_MAXint 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;// 初始化所有点对的邻接矩阵,权值为INFvector<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);// 初始化最短路径为 INFwhile(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 → ill from_i = (dis2[i] == INF ? INF : dis2[i]); // i → pres = max(res, to_i + from_i); // 计算最大往返路径}cout << res << endl;return 0;
}
第一次做到需要用到正反图的........自己真的考虑不到这个点(可能我很chun)