http://acm.hdu.edu.cn/showproblem.php?pid=1385
这个是模板题目。
核心算法:
从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。
采用的是(松弛技术),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);
其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]}
map[i,j]表示i到j的最短距离
K是穷举i,j的断点
map[n,n]初值应该为0,或者按照题目意思来做。
当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路
算法
1,从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
2,对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
===
把图用邻接距阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。
定义一个距阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。
把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min( G[i,j], G[i,k]+G[k,j] ),如果G[i,j]的值变小,则D[i,j]=k。
在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
算法易于理解及书写,但是时间复杂度太高。
#include<stdio.h> #include<string.h> #define MAX 9999999 int ans[1000][1000],map[1000][1000],tax[1000]; int vertex; int min(int a,int b) { return a<b?a:b; } void init() { int i,j; for(i=0;i<vertex;i++) for(j=0;j<vertex;j++) if(i==j)map[i][j]=0; else map[i][j]=MAX;//起点跟终点一致,说明可以0费用,否则就先初始化为最大 } void input() { int i,x,y,cost,j; for(i=0;i<vertex;i++) for(j=0;j<vertex;++j) { scanf("%d",&cost); if(cost!=-1) map[i][j]=cost; ans[i][j]=j; } for(i=0;i<vertex;++i) scanf("%d",&tax[i]); } int floyd() { int i,j,k,sum; for(k=0;k<vertex;++k) for(i=0;i<vertex;++i) for(j=0;j<vertex;++j) { sum=map[i][k]+map[k][j]+tax[k]; if(sum<map[i][j]) { map[i][j]=sum;//如果存在k点使得ij路径可松弛,那么就更新这条路径上的数据 ans[i][j]=ans[i][k];//存储该点的前一点 } else if(sum==map[i][j])//这里是为了字典序 { ans[i][j]=min(ans[i][j],ans[i][k]); } } } void print(int start,int end) { int k,i; printf("From %d to %d : ",start+1,end+1); printf("Path: %d",start+1); k=start; while(k!=end)//输出路径从起点到终点 { printf("-->%d",ans[k][end]+1); k=ans[k][end]; } printf(" "); printf("Total cost : %d ",map[start][end]); } int main() { int i,j,start,end; while(scanf("%d",&vertex),vertex) { init(); input(); floyd(); while(scanf("%d%d",&start,&end),start!=-1||end!=-1) print(start-1,end-1);//这里一定记得要把点跟下标对齐,即-1 } return 0; }