单源最短路径

来源:互联网 发布:夏老师c语言百度云 编辑:程序博客网 时间:2024/05/22 00:50

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更新数组distfor(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;}




原创粉丝点击