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

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
运行结果为:


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值