您的位置:首页 > 其它

有向无环图求单源最短路径问题

2015-11-28 22:20 387 查看
1,有向无环图可以用拓扑排序先求得拓扑序列;对于得到的拓扑序列,我们遍历一遍,对于每一个元素,我们看它的邻接边,(因为拓扑序列中当前元素只可能存在指向在它之后的元素的边),对它的邻接边做松弛操作,这样一遍过后,就得到了给定源节点的单源最短路径!

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

运行结果为:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: