算法训练 最短路
来源:互联网 发布:mac. wps 编辑:程序博客网 时间:2024/04/28 08:09
算法训练 最短路
时间限制:1.0s 内存限制:256.0MB
问题描述
给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。
输入格式
第一行两个整数n, m。
接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。
输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。
思路分析:首先要知道最短路常用的几种算法Dijkstra、Floyd、Bellman-Ford、SPFA、BFS。观察数据范围,顶点数最多有2W,用邻接矩阵存储图会内存超限,导致提交显示运行错误(其实就是内存炸了)。所以要用邻接表存储。因为图中有负权,Dijkstra不能用;因为图是带权的,所以BFS不能用;剩下的三个,好像都可以AC,Floyd时间复杂度较高,是立方级的,不建议用;Bellman-Ford时间复杂度也较高,有待考虑;最为稳妥的做法是用SPFA,SPFA就是利用队列优化过的Bellman-Ford。
先上一个Dijkstra的代码,可以通过80%数据,其余超时,利用小根堆优化理论应该可以AC(我有点疑问...不是Dijkstra不能处理带负权的图吗?还是不能处理带负环的图?)
#include <cstdio>#include <string>#include <vector>#define MAX 20000 + 10#define INF 0x3fffffffusing namespace std;typedef struct { int v; int l;} Edge;vector<Edge> MGraph[MAX];int dist[MAX];int visit[MAX];void Dijkstra( int n ) { fill( dist, dist + MAX, INF ); dist[0] = 0; for( int i = 0; i < n; i++ ) { // 这一部分是找最小值的过程,可以用小根堆优化 int u = -1, MIN = INF; for( int j = 0; j < n; j++ ) { if( !visit[j] && dist[j] < MIN ) { MIN = dist[j]; u = j; } } // if( u == -1 ) return; visit[u] = 1; for( int j = 0; j < MGraph[u].size(); j++ ) { int v = MGraph[u][j].v; if( !visit[v] ) { if( MGraph[u][j].l + dist[u] < dist[v] ) { dist[v] = dist[u] + MGraph[u][j].l; } } } }}int main() { int n, m; scanf( "%d%d", &n, &m ); int a, b, l; for( int i = 0; i < m; i++ ) { scanf( "%d%d%d", &a, &b, &l ); a--; b--; Edge e; e.v = b; e.l = l; MGraph[a].push_back( e ); } Dijkstra( n ); for( int i = 1; i < n; i++ ) { printf( "%d\n", dist[i] ); } return 0;}
下面这个是AC的SPFA算法,时间大约是400MS;我试了下用优先队列,需要600MS
#include <cstdio>#include <string>#include <vector>#include <queue>#include <string.h>#define MAX 20000 + 10#define INF 0x3fffffffusing namespace std;typedef struct { int v; int l;} Edge;vector<Edge> MGraph[MAX];int dist[MAX];int visit[MAX];int inq[MAX];int num[MAX];bool SPFA( int s, int n ) { // 初始化部分 memset( inq, false, sizeof( inq ) ); memset( num, 0, sizeof( num ) ); fill( dist, dist + MAX, INF ); // 源点入队部分 queue<int> Q; Q.push( s ); // 源点入队 inq[s] = true; // 源点已入队 num[s]++; // 源点入队次数加1 dist[s] = 0; // 主体部分 while( !Q.empty() ) { int u = Q.front(); // 队首顶点编号为u Q.pop(); inq[u] = false; // 设置u不在队列中 // 遍历u的所有邻接边v for( int j = 0; j < MGraph[u].size(); j++ ) { int v = MGraph[u][j].v; int dis = MGraph[u][j].l; // 松弛操作 if( dist[u] + dis < dist[v] ) { dist[v] = dist[u] + dis; if( !inq[v] ) { // 如果v不在队列中 Q.push( v ); // v入队 inq[v] = true; // 设置v为在队列中 num[v]++; // v的入队次数加1 if( num[v] >= n ) return false; // 有可达负环 } } } } return true; // 无可达负环}int main() { int n, m; scanf( "%d%d", &n, &m ); int a, b, l; for( int i = 0; i < m; i++ ) { scanf( "%d%d%d", &a, &b, &l ); a--; b--; Edge e; e.v = b; e.l = l; MGraph[a].push_back( e ); } SPFA( 0, n ); for( int i = 1; i < n; i++ ) { printf( "%d\n", dist[i] ); } return 0;}
1 0
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 算法训练 最短路
- 蓝桥杯 算法训练 最短路
- 蓝桥杯 算法训练 最短路
- 蓝桥杯-算法训练-最短路
- 算法训练 最短路 蓝桥杯
- 算法训练 最短路 spfa
- 算法训练 最短路 spfa
- 蓝桥杯算法训练 最短路
- 算法训练 最短路 (spfa算法)
- ANSYS Maxwell 16.1中solution data not readable处理方案
- 程序猿段子手
- Java中并发工具包 - 下
- Maven GC memory 内存溢出
- Mac搭建本地svn服务器,并用Cornerstone连接服务器
- 算法训练 最短路
- java求学之路
- 【MVC】action向view传值
- 这是一个毫无槽点(绝对没有)的开场白
- hive:orc file
- 【HDU 2003】求绝对值 水
- 在UI界面上加边框
- 相关FirDAC引用网址
- c——内置类型字面值