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