input 第一行两个数n, m分别为节点个数,路径的数目。接下来m行为路径。测试例以n == 0和m == 0结束
3 3
1 2 5
1 3 5
2 3 5
4 4
1 2 12 3 2
3 4 3
4 2 4
5 7
1 2 101 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;
}