您的位置:首页 > 理论基础 > 数据结构算法

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

2016-06-13 00:00 302 查看
一、概念

二、代码

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