CodeForces 20C Dijkstra? (最短路)
2014-04-15 20:06
537 查看
题目类型 图论 - 最短路
题目意思
给出一个最多包含 1e5 个点和 1e5 条边的图, 求1 -> n的最短路是多少
解题方法
最短路是一个经典的问题
还没掌握
Dijkstra算法 & Bellman-Ford算法 & SPFA & Floyd算法
这几种最短路算法的同学 猛戳 -> 最短路算法(Shortest Paths Algorithm)(几种算法的原理+代码)
注意
由于这道题的点和边的大小都达到了1e5,所以推荐使用 用堆优化过的Dijkstra算法 或 SPFA
用一个一维辅助数组int pre[MAXN]即可记录路径, 当一个点u可以用 dist[u] + edge(u, v) 更新 dist[v]时, pre[v] = u
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
优先队列+Dijkstra
题目意思
给出一个最多包含 1e5 个点和 1e5 条边的图, 求1 -> n的最短路是多少
解题方法
最短路是一个经典的问题
还没掌握
Dijkstra算法 & Bellman-Ford算法 & SPFA & Floyd算法
这几种最短路算法的同学 猛戳 -> 最短路算法(Shortest Paths Algorithm)(几种算法的原理+代码)
注意
由于这道题的点和边的大小都达到了1e5,所以推荐使用 用堆优化过的Dijkstra算法 或 SPFA
用一个一维辅助数组int pre[MAXN]即可记录路径, 当一个点u可以用 dist[u] + edge(u, v) 更新 dist[v]时, pre[v] = u
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
优先队列+Dijkstra
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> using namespace std; typedef long long LL; const int MAXN = 1e5 + 10; const LL INF = 1LL<<62; vector<int>e[MAXN]; vector<int>w[MAXN]; bool vis[MAXN]; LL d[MAXN]; int pre[MAXN]; int n; struct Node { LL d; int u; bool operator < (const Node & rhs) const { return d > rhs.d; } }; void Dijkstra() { priority_queue<Node>q; for( int i=1; i<=n; i++ ) d[i] = INF; d[1] = 0; memset(vis, 0, sizeof(vis)); Node tn; tn.d = 0, tn.u = 1; q.push(tn); while(!q.empty()) { Node t = q.top(); q.pop(); int u = t.u; if(vis[u]) continue; vis[u] = true; for( int i=0; i<e[u].size(); i++ ) { int v = e[u][i]; if(d[v] > d[u] + w[u][i]) { d[v] = d[u] + w[u][i]; pre[v] = u; tn.d = d[v], tn.u = v; q.push(tn); } } } } int main() { int m; while(scanf("%d%d", &n, &m) != EOF) { for( int i=1; i<=n; i++ ) e[i].clear(), w[i].clear(); int a, b, c; for( int i=0; i<m; i++ ) { scanf("%d%d%d", &a, &b, &c); e[a].push_back(b); w[a].push_back(c); e[b].push_back(a); w[b].push_back(c); } Dijkstra(); if(d == INF) printf("-1\n"); else { e[1].clear(); e[1].push_back(n); while(pre != 1) { n = pre ; e[1].push_back(n); } e[1].push_back(1); for( int i=e[1].size()-1; i>0; i-- ) printf("%d ", e[1][i]); printf("%d\n", e[1][0]); } } return 0; }SPFA - 注意用 vector 构造邻接表可能会导致超时, 所以可以用数组的方式构造邻接表, 不会的同学猛戳 -> ACM中关于图的邻接表的表示方法
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> using namespace std; typedef long long LL; const int MAXN = 1e5 + 10; const LL INF = 1LL<<62; bool vis[MAXN]; LL d[MAXN]; int pre[MAXN]; int n; int fa[MAXN]; int cnt; int n_res[MAXN]; struct P { int u, v, w; }node[MAXN*3]; bool SPFA() { memset(vis, 0, sizeof(vis)); queue<int>q; q.push(1); for( int i=1; i<=n; i++ ) d[i] = INF; d[1] = 0; vis[1] = 1; while(!q.empty()) { int f = q.front(); q.pop(); vis[f] = 0; for( int i=fa[f]; i!=-1; i=node[i].u ) { int v = node[i].v; if(d[v] > d[f] + node[i].w) { d[v] = d[f] + node[i].w; pre[v] = f; if(vis[v] == 0) { vis[v] = 1; q.push(v); //printf("push %d\n", v); } } } } return true; } int main() { int m; while(scanf("%d%d", &n, &m) != EOF) { memset(fa, -1, sizeof(fa)); int a, b, c; for( int i=0; i<m; i++ ) { scanf("%d%d%d", &a, &b, &c); node[cnt].u = fa[a]; node[cnt].v = b; node[cnt].w = c; fa[a] = cnt++; node[cnt].u = fa[b]; node[cnt].v = a; node[cnt].w = c; fa[b] = cnt++; } SPFA(); if(d == INF) printf("-1\n"); else { int k = 0; n_res[k++] = n; while(pre != 1) { n = pre ; n_res[k++] = n; } n_res[k++] = 1; for( int i=k-1; i>0; i-- ) printf("%d ", n_res[i]); printf("%d\n", n_res[0]); } } return 0; }
相关文章推荐
- python 线程,GIL 和 ctypes
- 使用命令行设置svn忽略列表
- leetcode-Candy(2014.2.25)
- CRecordSet操作数据库
- POJ2570
- easyui 打开多个tab页签,切换到第一次打开的页签时,其内容总是别的页签内容解决办法。
- leetcode-First Missing Positive(2014.2.25)
- 常见C++内存池技术
- poj3615
- CentOs yum遇到的小问题
- CreateThread()和_biginthreadex()
- leetcode-Jump Game(2014.2.23)
- 英文文档常用术语
- 一个简单的shell面试题引发的总结
- 新手开车 驾驶小秘诀要牢记
- 从原理角度解析Android (Java) http 文件上传
- Java—内部类
- 图片滤镜功能的代码设计
- 从原理角度解析Android (Java) http 文件上传
- 常见浏览器兼容性问题与解决方案