单源最短路径

input  第一行两个数n, m分别为节点个数,路径的数目。接下来m行为路径。测试例以n == 0和m == 0结束

3 3

1 2 5
1 3 5
2 3 5


4 4

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


5 7

1 2 10
1 4 25
1 5 80
2 3 40
3 5 10
4 3 20
4 5 50

0 0

output: 输出源点到所有其他各顶点的最短路径长度。接下来是各个顶点回到源点的路径

5 5

2 <--1

3<--1


1 3 6
2<--1
3<--2<--1
4<--3<--2<--1

10 45 25 55
2<--1
3<--4<--1
4<--1
5<--3<--4<--1

我自己的程序(这个程序因为没有大量的测试例可能有bug):

/*单源最短路径问题
采用贪心法类似于宽度搜索,到源点路径更短的最先到达那个节点,像病毒似得把它感染。
如何保证更短,优先队列。
*/
#include <iostream>
#include <cstring>
#include <fstream>
#include <queue>
using namespace std;
#define size 30
#define head 1			//设置源为节点1 

int n, m;				//n为节点数,m为要输入的关系数
int a[size][size];		//接受邻接矩阵
int parent[size];		//parent[i]表示直接到i的节点
int dis[size];			//dis[i]表示i节点到源的距离
struct edge{
	int from;			
	int to;
	int len;			//to这个节点到源的距离,跟dis[to]有点重复,这里用于优先队列
	bool operator < (const edge b) const{
		return len > b.len;
	}
};
priority_queue<edge> qu;

//输出到达路径函数
void output(int node){
	if(node == head){
		cout<<head<<endl;
		return;
	}
	cout<<node<<"<--";
	output(parent[node]);
}

//处理函数
void bfs(){
	int i;
	dis[head] = 0;
	edge e1;
	for(i = 1; i <= n; i++){
		if(a[head][i] != 0){
			e1.from = head;
			e1.to = i;
			e1.len = a[head][i] + dis[head];
			dis[e1.to] = e1.len;
			qu.push(e1);
		}
	}
	while(!qu.empty()){
		e1 = qu.top();
		qu.pop();
		if(parent[e1.to] != 0)		//已经有父节点了,有更短的路径先到达。这一点也可防止环的发生
			continue;
		int now = e1.to;
		parent[now] = e1.from;
		dis[e1.to] = e1.len;
		for(i = 1; i <= n; i++){	//把now的相应可到达的地方也列举出来
			if(a[now][i] != 0 && parent[i] == 0){	//parent[i] == 0可防止环,也可防后面到他的对距离影响
				e1.from = now;
				e1.to = i;
				e1.len = a[now][i] + dis[now];
				qu.push(e1);
			}
		}
	}
}

int main(){
	//fstream cin("in.txt");
	int i, temp1, temp2, len;

	while(cin>>n>>m && n && m){
		memset(a, 0, sizeof(a));
		memset(parent, 0, sizeof(parent));
		for(i = 1; i <= m; i++){
			cin>>temp1>>temp2>>len;
			a[temp1][temp2] = len;
		}
		bfs();

		//以下为输出部分
		for(i = 2; i <= n; i++){
			cout<<dis[i];
			if(i != n)
				cout<<" ";
		}
		cout<<endl;
		for(i = 2; i <= n; i++){
			output(i);
		}
		cout<<endl;
	}
    return 0;
}



2013-13-8-3

下面是算法分析设计中的dijkstra程序,跟上面写法上略有不同

#include<stdio.h>
#include<string.h>

#define NUM 100
#define maxint 10000

//顶点个数n,源点v,有向图的邻接矩阵为c
//数组dist保存从源点v到每个顶点的最短特殊路径长度
//数组prev保存每个顶点在最短特殊路径上的前一个结点
void dijkstra(int n,int v,int dist[],int prev[],int c[][NUM])
{
	int i,j;
	bool s[NUM];	//集合S
	//初始化数组
	for(i=1; i<=n; i++)
	{
		dist[i] = c[v][i];
		s[i] = false;
		if (dist[i]>maxint) 
			prev[i] = 0;
		else 
			prev[i] = v;
	}
	//初始化源结点
	dist[v] = 0;
	s[v] = true;
	//其余顶点
	for(i=1; i<n; i++)
	{
		//在数组dist中寻找未处理结点的最小值
		int tmp = maxint;
		int u = v;
		for(j=1; j<=n; j++){
			if(!(s[j]) && (dist[j]<tmp))
			{
				u = j;
				tmp = dist[j];
			}
		}
		s[u] = 1;		//结点u加入s中
		//利用结点u更新数组dist
		for(j=1; j<=n; j++)
			if(!(s[j]) && c[u][j]<maxint)
			{
				//newdist为从源点到该点的最短特殊路径
				int newdist = dist[u]+c[u][j];
				if (newdist<dist[j])
				{
					//修正最短距离
					dist[j] = newdist;
					//记录j的前一个结点
					prev[j] = u;
				}
			}
	}
}

int main()
{
	//freopen("in.txt", "r", stdin);
	int m,n;
	while(scanf("%d%d",&n,&m)!=EOF && (m || n))
	{
		int i,j;
		int dist[NUM] = {0};
		int prev[NUM] = {0};
		int c[NUM][NUM];
		memset(c,1,sizeof(c));
		int v,w,edge;
		for(i=0; i<m; i++)
		{
			scanf("%d%d%d",&v,&w,&edge);
			c[v][w] = edge;
		}
		dijkstra(n,1,dist,prev,c);

		//一下为输出部分
		for(i=2; i<=n; i++)
			printf("%d ",dist[i]);
		printf("\n");
		for(j=2; j<=n; j++)
		{
			printf("%d",j);
			int t = prev[j];
			while (t!=1)
			{
				printf("-->%d",t);
				t=prev[t];
			}
			printf("-->1\n");
		}
	}
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值