有向无环图求单源最短路径问题
2015-11-28 22:20
387 查看
1,有向无环图可以用拓扑排序先求得拓扑序列;对于得到的拓扑序列,我们遍历一遍,对于每一个元素,我们看它的邻接边,(因为拓扑序列中当前元素只可能存在指向在它之后的元素的边),对它的邻接边做松弛操作,这样一遍过后,就得到了给定源节点的单源最短路径!
2,时间复杂度分析:
拓扑排序的时间复杂度为O(n+e),遍历一遍拓扑序列,以及松弛操作的代价为O(n+e);所以总的时间代价为O(n+e).
3,下边是简单实现:
12 16
0 1 2
0 2 -1
1 2 3
0 3 4
2 4 5
3 4 10
10 5 3
4 6 7
2 6 21
2 7 -5
5 7 9
8 9 11
8 10 6
8 11 4
9 11 10
0 11 11
运行结果为:
2,时间复杂度分析:
拓扑排序的时间复杂度为O(n+e),遍历一遍拓扑序列,以及松弛操作的代价为O(n+e);所以总的时间代价为O(n+e).
3,下边是简单实现:
#include "stdafx.h" #include <iostream> #include <stack> #include <fstream> using namespace std; typedef int ElemType; #define path "D:\\test1.txt" #define INFENITE 65535 struct DAGNode{ ElemType data; struct arcnode *firstarc; }; struct arcnode{ ElemType adjvex; struct arcnode *nextarc; int weight; arcnode(ElemType x, int y) { adjvex = x; weight = y; nextarc = NULL; } }; struct DAG{ int vernum; int arcnum; int *indegree;//入度数组 ElemType *pre;//前驱数组,pre[i]表示的是顶点i的最短路径上的前驱顶点 int *dist;//距离数组 DAGNode *AdjList; }; void Readfile(DAG &g) { cout << "读入图的顶点数和边数并输出!" << endl; ifstream infile(path); infile >> g.vernum >> g.arcnum; cout << g.vernum << ' ' << g.arcnum << endl; cout << "建立邻接表!" << endl; g.AdjList = new DAGNode[g.vernum]; g.indegree = new int[g.vernum]; g.pre = new ElemType[g.vernum]; g.dist = new int[g.vernum]; for (int i = 0; i < g.vernum; i++)//初始化 { g.AdjList[i].data = i; g.AdjList[i].firstarc = NULL; g.indegree[i] = 0; g.pre[i] = i; g.dist[i] = INFENITE; } ElemType head, tail; int weight; for (int j = 0; j < g.arcnum; j++) { infile >> head >> tail >> weight; arcnode *s = new arcnode(tail, weight); s->nextarc = g.AdjList[head].firstarc; g.AdjList[head].firstarc = s;//头插法 g.indegree[tail]++;//tail顶点入度增加 } } void TuoPuSort(DAG &g, ElemType *&e)//e是存储拓扑序列 { e = new ElemType[g.vernum]; stack <ElemType> s; for (int i = 0; i < g.vernum; i++) { if (!g.indegree[i]) { s.push(i);//零入度顶点入栈 } } int count = 0;//出栈次数 while (!s.empty()) { e[count] = s.top(); //cout << s.top() << endl; s.pop();//出栈,所有邻接点的入度减少1 arcnode *t; for (t = g.AdjList[e[count]].firstarc; t; t = t->nextarc) { g.indegree[t->adjvex]--; if (!g.indegree[t->adjvex]) { s.push(t->adjvex); } } count++; } } void Relax(DAG &g, ElemType u, ElemType v, int weight) { if (g.dist[u] == INFENITE) { return; } if (g.dist[v] > g.dist[u] + weight) { g.dist[v] = g.dist[u] + weight; g.pre[v] = u; } } void ShortRoot(DAG &g, ElemType source, ElemType *s) { g.dist[source] = 0; for (int i = 0; i < g.vernum; i++) { arcnode *t; for (t = g.AdjList[s[i]].firstarc; t; t = t->nextarc) { Relax(g, s[i], t->adjvex, t->weight); } } } void printroot(DAG g, ElemType x) { //反向打印出 if (g.dist[x] == INFENITE) { cout << "该点源节点不可达!" << endl; } else { while (g.pre[x] != x) { cout << x << "-->"; x = g.pre[x]; } cout << x; } } int _tmain(int argc, _TCHAR* argv[]) { DAG g; Readfile(g); ElemType *e = NULL; TuoPuSort(g, e); cout << "拓扑序列为:" << endl; for (int i = 0; i < g.vernum; i++) { cout << e[i] << "-->"; } cout << endl; cout << "最短路径:" << endl; ShortRoot(g, 0, e); printroot(g, 6); cout << endl; cout << "最短距离为:" << g.dist[6]; system("pause"); return 0; }test1.txt数据为:
12 16
0 1 2
0 2 -1
1 2 3
0 3 4
2 4 5
3 4 10
10 5 3
4 6 7
2 6 21
2 7 -5
5 7 9
8 9 11
8 10 6
8 11 4
9 11 10
0 11 11
运行结果为:
相关文章推荐
- C语言开发总结(十五)
- Open CV 三帧差法
- git commit 提交注释规范
- [转载]微信企业号开发如何建立连接
- 一个朋友js图表开发遇到的问题 解决思路c和js
- 【iOS】containsString iOS7 报错
- ECMAScript定义类或对象
- CentOS下安装xampp
- 单链表的修改和删除
- 第二个spring冲刺第5天
- poj 3617 Best Cow Line 【贪心】
- java中ThreadLoacl解析
- bzoj 4295 Hazard 【循环】【单调队列】【扫描】
- CSS解决未知高度垂直居中
- 多线程问题基本pv问题
- 同步函数,静态同步函数,同步代码块
- ASP.NET WebAPI 14 仿写Filter管道
- 如何使用PDO查询Mysql来避免SQL注入风险?ThinkPHP 3.1中的SQL注入漏洞分析!
- 网际协议
- bpptstrao popover data-container 无效