7-5 单源最短路径(超级无敌详细)

请编写程序求给定正权有向图的单源最短路径长度。图中包含n个顶点,编号为0至n-1,以顶点0作为源点。

输入格式:

输入第一行为两个正整数n和e,分别表示图的顶点数和边数,其中n不超过20000,e不超过1000。接下来e行表示每条边的信息,每行为3个非负整数a、b、c,其中a和b表示该边的端点编号,c表示权值。各边并非按端点编号顺序排列。

输出格式:

输出为一行整数,为按顶点编号顺序排列的源点0到各顶点的最短路径长度(不含源点到源点),每个整数后一个空格。如源点到某顶点无最短路径,则不输出该条路径长度。

输入样例:

4 4
0 1 1
0 3 1
1 3 1
2 0 1

输出样例:

1 1 

 解题思路:

1.求单源最短路径问题考虑用Dijkstra算法。

2.本题节点数过多,图过大,用邻接矩阵会段错误,所以用邻接表。

3.定义一个int dist[]用来储存源点到各点的最短距离,初始化为0;定义一个int visit[]来判断是否已经找到源点到该点的最短路径。

4.建立好邻接表后先将源点能够直接到达的点和距离添加到dist[]中。每次从中找到最短的一条,并靠该点的信息更新dist[];

代码如下:

#include<bits/stdc++.h>
using namespace std;
//data为到达的点,weight为到达该点的距离。
struct vertex{
	int data,weight;
	vertex* next;
};
//dist[]数组用来存储源点到各点的最短距离,visit[]用来标记是否找到了从源点到该点的最短距离。
int dist[20005],visit[20005];
//创建图
struct {
	int numv, nume;
	vertex vertices[20005];
}G;
//输入边的信息,构建图
void join() {
	int x, y;
	cin >> x >> y;
	vertex* t=new vertex;
    t->data = y;
    cin >> t->weight;
	t->next = G.vertices[x].next;
	G.vertices[x].next = t;
}
//找到dist[]中最小的一条边,返回下标
int findmin(){
	int min = INT_MAX;
	int index = -1;
	for (int i = 0; i < G.numv; ++i) {
//要注意dist【i】不能等于0(因为等于0表示没有边),且visit[i]==0(表示没有被找到最短距离的点)
		if (dist[i] < min&&visit[i]==0&&dist[i]!=0) {
			min = dist[i];
			index = i;
		}
	}
	return index;
}
void Dijkstra() {
//源点不用找,所以要找G.numv-1个点加入进去
    int N=G.numv-1;
//源点已经被找到
	visit[0] = 1;
	while (N-->0) {
		int a = findmin();
//当a==-1的时候就说明dist中已经没有满足dist[i]!=0(有边)&&visit[i]==0(没被访问)的点了;
//这时候就直接不用找了,break.
        if(a==-1)break;
//能找到就把这个点标记
		visit[a] = 1;
//找这个新加入的点,是否会令源点到达其他点的距离更短
//因为该邻接表储存的出度,所以到这个点的链表中找,t->data是从这个点到达的其他点,如果(源点到其他点的距离>源点到该点的距离+该点到其他点的距离)||(源点到不了该点)那么就更新;
		vertex* t = G.vertices[a].next;
		while (t != NULL) {
//如果
			if (dist[t->data] > (dist[a] + t->weight) || dist[t->data] == 0) {
				dist[t->data] = dist[a] + t->weight;
			}
            t=t->next;
		}
	}
}
int main() {
	cin >> G.numv >> G.nume;
//初始化,可有可无
	for (int i = 0; i < G.numv; ++i) {
		G.vertices[i].data = i;
		G.vertices[i].next = NULL;
	}
//加入边,构建图
	while (G.nume--) {
		join();
	}
//初始化源点能够直接到达的距离;
	vertex* head = G.vertices[0].next;
	while (head!=NULL) {
		dist[head->data] = head->weight;
		head = head->next;
	}
	Dijkstra();
//输出,注意这里必须i=1,不能写i=0;因为他有可能给0 0 5这种边,下面的话写if(dist[i]!=0)cout的话到他本身会输出5,这里直接把到它本身跳过去就行了.好恶心!!!!
	for (int i = 1; i < G . numv; ++i) {
		if(dist[i]!=0)cout << dist[i] << " ";
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值