Poj3255 Roadblocks SPFA算法解“次短路”问题 代码&注释
2016-09-03 14:22
211 查看
题目大意:给定一个无向图,图顶点数N≤5000,边数R≤100000,求顶点1到顶点N的“次短路”。
注意:
多次经过同一顶点或同一条边的路径是被允许的(允许有环的路径存在)。
“次短路“指的是数值上的次短,例如,顶点1到N有两条最短路径,长度均为100,还有一条路径长为101,则次短路长度应输出101,而非100。
注意:
多次经过同一顶点或同一条边的路径是被允许的(允许有环的路径存在)。
“次短路“指的是数值上的次短,例如,顶点1到N有两条最短路径,长度均为100,还有一条路径长为101,则次短路长度应输出101,而非100。
// Poj 3255 Roadblocks // By Victor Li // 2016-09-03 // SPFA算法解次短路问题 // SPFA算法不一定局限于求解最短路问题,图中的有状态表示和转移的最优化问题都可以考虑应用SPFA算法的变种来处理 // SPFA算法适用于稀疏图 #include <stdio.h> #include <stdlib.h> #include <queue> using namespace std; const int oo = 5*10e8; struct enode{ int v; int d; enode * next; }; void addEdge(int x, int y, int d, enode **e, enode **en){ if (en[x] == 0){ e[x] = new enode; e[x]->v = y; e[x]->d = d; e[x]->next = NULL; en[x] = e[x]; } else { en[x]->next = new enode; en[x]->next->v = y; en[x]->next->d = d; en[x]->next->next = NULL; en[x] = en[x]->next; } } //松弛操作 int relax(int x, int y, int d, int * dist){ if (dist[x] + d < dist[y]){ int tmp = dist[y]; dist[y] = dist[x] + d; return tmp; } else return -1; } int main(){ int n, m, x, y, d, tmp; scanf("%d%d",&n,&m); //用链表存储每个顶点连接的所有边的信息;e[i]为顶点i对应的边链表的表头 //为了提高构建边链表的效率,用en[i]存储顶点i对应的边链表的末尾 enode ** e = (enode **) calloc(n, sizeof(enode *)); enode ** en = (enode **) calloc(n, sizeof(enode *)); for (int i=0;i<m;i++){ scanf("%d%d%d",&x,&y,&d); --x; --y; addEdge(x,y,d,e,en); addEdge(y,x,d,e,en); } //0 =< i < n : dist[i] 从顶点0到顶点i的最短路长度 //n =< i < 2*n : dist[i] 从顶点0到顶点i-n的次短路的长度 int * dist = (int *) calloc(2*n, sizeof(int )); for (int i=1;i<2*n;i++) dist[i] = oo; bool * flag = (bool *) calloc(2*n, sizeof(bool)); flag[0] = true; //应用SPFA算法求解 queue<int> Q; Q.push(0); while (!Q.empty()){ x = Q.front(); Q.pop(); flag[x] = false; if (x<n) { enode * et = e[x]; while (et!=NULL){ //这里使用tmp记录下了“松弛”过程中被更短的路径顶掉的之前的最短路径的长度 //记录下它是因为它有可能是到达该顶点的“次短路”,可以用来更新dist[et->v+n] if ( (tmp = relax(x,et->v,et->d,dist))>-1 ){ if (!flag[et->v]){ Q.push(et->v); flag[et->v] = true; } if ( tmp<dist[et->v+n]){ dist[et->v+n] = tmp; if (!flag[et->v+n]){ Q.push(et->v+n); flag[et->v+n] = true; } } } else { //当前路径长度更新不了到达该节点的最短路径,则再尝试更新次短路径 if ( dist[x]+et->d>dist[et->v] && relax(x,et->v+n,et->d,dist)>-1 ) if (!flag[et->v+n]){ Q.push(et->v+n); flag[et->v+n] = true; } } et = et->next; } } else { //x>=n,说明当前的队头对应的是一条“次短路径” //次短路径不可能经过一条边到达下一个顶点时就成为到达下一顶点的最短路径 //因此这里只考虑更新下一顶点的次短路径的情况 enode * et = e[x-n]; while (et!=NULL){ if (relax(x,et->v+n,et->d,dist)>-1) if (!flag[et->v+n]){ Q.push(et->v+n); flag[et->v+n] = true; } et = et->next; } } } //该算法可以求出到达图中每一节点的最短路径和次短路径 printf("%d\n",dist[2*n-1]); return 0; }
相关文章推荐
- 解决vs2010中写vb代码时按'''不自动加入函数注释的问题
- UserControl 的一个值得注意的问题 [属性" * "的代码生成失败.错误是:"程序集"*.Version=1.0.0.0,Culture=neutral,..........无标记为序列化"
- 解决VS2008中日文代码注释乱码的问题
- "ubuntu 下 eclipse 代码提示功能显示后焦点不在eclipse内,需点击窗口才行 “ 问题的解决
- EA代码工程---轻松几步教你更改"EA生成的源代码表头注释格式"
- 最短路径实现代码-->Dijkstra求解最短路径问题
- 去注释傻瓜机&&对JAVA代码加密的尝试
- Myeclipse 代码排序 快捷键"Ctrl + Shift + f"失灵的问题
- Myeclipse 代码排序 快捷键"Ctrl + Shift + f"失灵的问题
- C# <summary> 三纲注释的设置问题
- 码代码时碰到的一些小问题 & Xcode的一些使用方法
- 执行CreateObject("Scripting.FileSystemObject")代码遇到"Operation is disallowed in this session"问题
- 是雏还是鹰——编程规范之代码注释
- win7下修改注册表问题 模块"jscript.dll"已加载,但对DllRegisterServer的调用失败,错误代码为0x80004005 我是WIN7
- asp.net中,在客户端,加入<%=....%>代码时出现的问题解决方法
- 解决VS2008 有时右键不显示"查看代码" 选项的问题
- 崩溃,source Insight显示linux代码中文注释乱码问题,以及很傻很天真的解决方法
- 哥发明的 一个ssh整合时解决dao层代码冗余问题的"一点儿不漏"型抽取法!!!!
- [java]中代码注释问题
- VS2008 打开"视图设计器" 和 "查看代码"提示没有可用的编辑器问题