poj2457 Part Acquisition(dijkstra||spfa+路径记录优化)
来源:互联网 发布:2009年网络歌曲大全 编辑:程序博客网 时间:2024/06/06 07:03
http://poj.org/problem?id=2457
题意:m个关系n个货物,关系中的a b代表可以拿货物a换取货物b,构造一条最短路,起点1终点n,输出交换次数和路径。
思路:看了这个教程。注意是有向图。dijkstra和spfa事实上是一个思路,都是找到最短路后,沿着这条路根据找路时存储的前驱来存储相应的节点。记录路径的方式也有几种,刚开始用数组记录,绕的我头都晕了。后来用栈优化,一目了然。
这题后来也回顾过,好好想了想初始化问题。dijkstra和spfa其实都可以一开始就将dis数组置为无穷大,pre数组更新为-1。dijkstra中仅仅把dis[1]置为0,但是未访问,这样所有的点都能算上。spfa中第一个点要入队列,dis[1]置为0,变成已访问,同样可以算上所有的点。
这样初始化就不会对起点进行一些对pre和dis的繁琐操作,使思路更加清晰。
首先来终极简化版本,以后做路径题方式就是以这个为参考:
#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>#include <queue>#include <stack>using namespace std;typedef long long LL;const int N = 1005;const int INF = 0x3f3f3f3f;int dis[N], G[N][N], pre[N], ans[N], n;bool vis[N];void dijkstra(int s){ memset(vis, false, sizeof(vis)); memset(pre, -1, sizeof(pre)); for(int i = 1; i <= n; i++) dis[i] = INF; dis[s] = 0; for(int i = 1; i <= n; i++) { int k = -1; for(int j = 1; j <= n; j++) { if(!vis[j] && (k==-1 || dis[j]<dis[k])) k = j; } if(k == -1) break;//已经遍历所有的点 vis[k] = true; for(int j = 1; j <= n; j++) { if(!vis[j] && dis[k]+G[k][j]<dis[j]) { dis[j] = dis[k]+G[k][j]; pre[j] = k; } } }}void spfa(int s){ memset(vis, false, sizeof(vis)); memset(pre, -1, sizeof(pre)); queue<int>que; for(int i = 1; i <= n; i++) dis[i] = INF; dis[s] = 0; vis[s] = true; que.push(s); while(!que.empty()) { int now = que.front(); que.pop(); vis[now] = false; for(int i = 1; i <= n; i++) { if(dis[now]+G[now][i]<dis[i]) { dis[i] = dis[now]+G[now][i]; pre[i] = now; if(!vis[i]) { vis[i] = true; que.push(i); } } } }}void Print(){ stack<int>path; int now = n, cnt = 0; if(dis[n] == INF) printf("-1\n"); else { while(now != -1) { path.push(now); now = pre[now]; cnt++; } printf("%d\n", cnt); while(!path.empty()) { printf("%d\n", path.top()); path.pop(); } }}int main(){ // freopen("in.txt", "r", stdin); int m, s, e; scanf("%d%d", &m, &n); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i == j) G[i][j] = 0; else G[i][j] = INF; } for(int i = 1; i <= m; i++) { scanf("%d%d", &s, &e); G[s][e] = 1; } // dijkstra(1); spfa(1); Print(); return 0;}
然后是这个把我绕晕了的数组记录路径:
#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>#include <queue>#include <stack>using namespace std;typedef long long LL;const int N = 1005;const int INF = 0x3f3f3f3f;int dis[N], G[N][N], pre[N], ans[N], n;bool vis[N];void dijkstra(int s){ memset(vis, false, sizeof(vis)); memset(pre, -1, sizeof(pre)); for(int i = 1; i <= n; i++) { dis[i] = G[s][i]; if(dis[i]!=INF && i!=s) pre[i] = s; } dis[s] = 0; vis[s] = true; for(int i = 1; i <= n; i++) { int k = -1; for(int j = 1; j <= n; j++) { if(!vis[j] && (k==-1 || dis[j]<dis[k])) k = j; } if(k == -1) break;//已经遍历所有的点 vis[k] = true; for(int j = 1; j <= n; j++) { if(!vis[j] && dis[k]+G[k][j]<dis[j]) { dis[j] = dis[k]+G[k][j]; pre[j] = k; } } }}void spfa(int s){ memset(vis, 0, sizeof(vis)); memset(pre, -1, sizeof(pre)); queue<int>que; for(int i = 1; i <= n; i++) dis[i] = INF;//初值记得赋无穷,而不是G数组中的值! dis[s] = 0; vis[s] = true; que.push(s); while(!que.empty()) { int now = que.front(); que.pop(); vis[now] = false;//记得还原!! for(int i = 1; i <= n; i++) { if(dis[now]+G[now][i]<dis[i]) { dis[i] = dis[now]+G[now][i]; pre[i] = now; if(!vis[i]) { vis[i] = true; que.push(i); } } } }}void print(){ memset(ans, 0, sizeof(ans)); int cnt = 0; if(dis[n] == INF) printf("-1\n"); else { ans[cnt++] = n; int tmp = pre[n]; while(tmp != -1) { ans[cnt++] = tmp; tmp = pre[tmp]; } printf("%d\n", cnt); for(int i = cnt-1; i >= 0; i--) printf("%d\n", ans[i]); // printf("sad"); }}int main(){ // freopen("in.txt", "r", stdin); int m, s, e; scanf("%d%d", &m, &n); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i == j) G[i][j] = 0; else G[i][j] = INF; } for(int i = 1; i <= m; i++) { scanf("%d%d", &s, &e); G[s][e] = 1; }// dijkstra(1); spfa(1); print(); return 0;}
后来用两种floyd敲了两次,都是TLE。大体思路就是二维数组在DP的时候已经将路径的前驱保存了下来,我们正好利用了这种特殊的性质。记录前驱就和前面思想一样,记录后继很方便,就是floyd的特权吧,然而复杂度太高,人家不让过哎= =
floyd记录前驱的路径记录法:
#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>#include <queue>using namespace std;typedef long long LL;const int N = 1005;const int INF = 0x3f3f3f3f;int G[N][N], pre[N][N], ans[N], n;void floyd(){ for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(G[i][k]+G[k][j] < G[i][j]) { G[i][j] = G[i][k]+G[k][j]; pre[i][j] = pre[k][j]; } } pre[1][1] = -1;}void print(){ memset(ans, 0, sizeof(ans)); int cnt = 0; if(G[1][n] == INF) printf("-1\n"); else { ans[cnt++] = n; int tmp = pre[1][n]; while(tmp != -1) { ans[cnt++] = tmp; tmp = pre[1][tmp]; } printf("%d\n", cnt); for(int i = cnt-1; i >= 0; i--) printf("%d\n", ans[i]); }}int main(){ // freopen("in.txt", "r", stdin); int m, s, e; scanf("%d%d", &m, &n); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i == j) G[i][j] = 0; else G[i][j] = INF; pre[i][j] = i; } for(int i = 1; i <= m; i++) { scanf("%d%d", &s, &e); G[s][e] = 1; } floyd(); print(); return 0;}
floyd记录后继的路径记录法:
#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>#include <queue>using namespace std;typedef long long LL;const int N = 1005;const int INF = 0x3f3f3f3f;int G[N][N], pre[N][N], n;void floyd(){ for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(G[i][k]+G[k][j] < G[i][j]) { G[i][j] = G[i][k]+G[k][j]; pre[i][j] = pre[i][k]; } } pre[n][n] = -1;}void print(){ int cnt = 0; if(G[1][n] == INF) printf("-1\n"); else { printf("%d\n", G[1][n]+1); int tmp = pre[1][n]; printf("%d\n", 1); while(tmp != -1) { printf("%d\n", tmp); tmp = pre[tmp][n]; } }}int main(){ // freopen("in.txt", "r", stdin); int m, s, e; scanf("%d%d", &m, &n); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i == j) G[i][j] = 0; else G[i][j] = INF; pre[i][j] = j; } for(int i = 1; i <= m; i++) { scanf("%d%d", &s, &e); G[s][e] = 1; } floyd(); print(); return 0;}
0 0
- poj2457 Part Acquisition(dijkstra||spfa+路径记录优化)
- POJ2457 Part Acquisition(Spfa最短路+记录路径)
- POJ 2457 Part Acquisition (Dijkstra + 记录路径)
- poj2457 - Part Acquisition (最短路径问题)(邻接表 Dijkstra + 并查集 )
- POJ2457 Part Acquisition
- POJ2457 Part Acquisition
- poj2457 Part Acquisition
- Part Acquisition--(最短路径,Dijkstra)
- 【最短路】poj2457 SPFA+记录路径
- poj2457--dijkstra算法的路径记录
- POJ 2457 Part Acquisition(记录路径单源最短路)
- POJ 2457 Part Acquisition【Dij+记录路径】
- Part Acquisition(最短路径Dijkstra算法+路径输出)
- poj 2457 Part Acquisition 【spfa最短路 + STL路径输出】
- POJ 2457--Part Acquisition 【spfa最短路 + STL路径输出】
- Dijkstra?+spfa+路径的记录
- poj 2457 Part Acquisition-dijkstra
- POJ Part Acquisition 2457 dijkstra
- TCP通信流程解析
- 最新CocoaPods安装教程,保证可用
- 多项式加减运算—c语言描述
- "挑战杯"一次出乎意料的比赛
- Android高效加载大图、多图解决方案,有效避免程序OOM
- poj2457 Part Acquisition(dijkstra||spfa+路径记录优化)
- php源码之遍历目录下的所有的文件
- RTSP协议学习
- CSS 概述&与html结合四种方式
- IT-mysql-数据插入
- 基础算法系列
- MySQL存储过程
- 【软件项目管理】用例分析方法采用一种面向对象的情景分析方法
- C语言调用matlab引擎和调用matlab生成的DLL文件