算法导论-24.2-有向无回路图中的单源最短路径

一、概念

二、代码

#include <iostream>
#include <queue>
using namespace std;

#define N 6
#define M 10

//边结点结构
struct Edge
{
	int start;//有向图的起点
	int end;//有向图的终点
	Edge *next;//指向同一个起点的下一条边
	int weight;//边的类型
	Edge(int s, int e,int w):start(s),end(e),weight(w),next(NULL){}
};
//顶点结点结构
struct Vertex
{
	int id;
	Edge *head;//指向以该顶点为起点的下一条边
	int degree;
	int d;
	int p;
	Vertex(int i):head(NULL),degree(0),id(i),p(-1){}
};
//图结构
struct Graph
{
	Vertex *V[N+1];//N个顶点
	Graph()
	{
		int i;
		for(i = 1; i <= N; i++)
			V[i] = new Vertex(i);
	}
	~Graph()
	{
		int i;
		for(i = 1; i <= N; i++)
			delete V[i];
	}
};

queue<int> Q;
int time = 0, Top[N+1] = {0};

void Print(Graph *G)
{
	int i;
	cout<<"d:";
	for(i = 1; i <= N; i++)
		cout<<G->V[i]->d<<' ';
	cout<<endl;
	cout<<"p:";
	for(i = 1; i <= N; i++)
		cout<<G->V[i]->p<<' ';
	cout<<endl;
}
//插入边
void InsertEdge(Graph *G, Edge *E)
{
	//如果没有相同起点的边
	if(G->V[E->start]->head == NULL)
		G->V[E->start]->head =E;
	//如果有,加入到链表中,递增顺序排列,便于查重
	else
	{
		//链表的插入,不解释
		Edge *e1 = G->V[E->start]->head, *e2 = e1;
		while(e1 && e1->end < E->end)
		{
			e2 = e1;
			e1 = e1->next;
		}
		if(e1 && e1->end == E->end)
			return;
		if(e1 == e2)
		{
			E->next = e1;
			G->V[E->start]->head =E;
		}
		else
		{
			e2->next = E;
			E->next = e1;
		}
		//插入边的同时,计下每个顶点的入度
		G->V[E->end]->degree++;
	}
}
//拓扑排序
void Topological(Graph *G)
{
	//队列初始化
	while(!Q.empty())
		Q.pop();
	int i;
	//将所有入度为0的点入队列
	for(i = 1; i <= N; i++)
	{
		if(G->V[i]->degree == 0)
			Q.push(i);
	}
	//队列不为空
	while(!Q.empty())
	{
		//队列首元素
		int t = Q.front();
		Q.pop();
		//输出
		cout<<t<<' ';
		Top[++Top[0]] = t;
		//处理以头结点为起点的所有的边
		Edge *e = G->V[t]->head;
		while(e)
		{
			//将边的终点的入度-1
			G->V[e->end]->degree--;
			//若入度减为0,则入队列
			if(G->V[e->end]->degree == 0)
				Q.push(e->end);
			e = e->next;
		}
	}
	cout<<endl;
}
//初始化
void Initialize_Single_Source(Graph *G, int s)
{
	int i;
	for(i = 1; i <= N; i++)
	{
		G->V[i]->d = 0x7fffffff;
		G->V[i]->p = -1;
	}
	G->V[s]->d = 0;
}
//松弛技术
void Relax(Vertex* u, Vertex* v, int w)
{
	if(u->d != 0x7fffffff && v->d > u->d + w)
	{
		v->d = u->d + w;
		v->p = u->id;
	}
}
void Dag_Shortest_Paths(Graph *G, int s)
{
	//拓扑排序并输出,时间O(V+E)
	Topological(G);
	//初始化O(V)
	Initialize_Single_Source(G, s);
	//对每个顶点进行一次迭代
	for(int i = 1; i <= N; i++)
	{
		cout<<"对第"<<i<<"个点进行松弛后"<<endl;
		Vertex *u = G->V[Top[i]];
		Edge *e = u->head;
		while(e)
		{
			Relax(u,G->V[e->end], e->weight);
			e = e->next;
		}
		Print(G);
	}
}
/*
1 2 5
2 3 2
3 4 7
4 5 -1
5 6 -2
1 3 3
2 4 6
3 5 4
3 6 2
4 6 1
*/
int main()
{
	//构造一个空的图
	Graph *G = new Graph;
	Edge *E;
	//输入边
	int i,weight, start, end;
	for(i = 1; i <= M; i++)
	{
		cin>>start>>end>>weight;
		E = new Edge(start, end,weight);
		InsertEdge(G, E);
	}
	//有向
	int s;
	cin>>s;
	Dag_Shortest_Paths(G, s);
	return 0;
}


三、练习

24.2-1

r:1, s:2, t:3, x:4, y:5, z:6

拓扑排序结果:
1 2 3 4 5 6
对第1个点进行松弛后
d:0 5 3 2147483647 2147483647 2147483647
p:-1 1 1 -1 -1 -1
对第2个点进行松弛后
d:0 5 3 11 2147483647 2147483647
p:-1 1 1 2 -1 -1
对第3个点进行松弛后
d:0 5 3 10 7 5
p:-1 1 1 3 3 3
对第4个点进行松弛后
d:0 5 3 10 7 5
p:-1 1 1 3 3 3
对第5个点进行松弛后
d:0 5 3 10 7 5
p:-1 1 1 3 3 3
对第6个点进行松弛后
d:0 5 3 10 7 5
p:-1 1 1 3 3 3

 

24.2-3

将所有点的d初始化为0,RELAX(u,v,w)时的if条件为:d[v] < d[u] + w(u, v)

 

24.2-4

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值