题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2112
这一题与上面的图论的题有很大不同,对于这一题对于这题有两种解法,Dijkstra算法或者floyd算法,只是我也没理解好,在别人的帮助下勉强整出dijkstra算法解这一题,
由于题目本身比上几个稍微难理解点,所以附上dijkstra算法的课件的部分;
Dijkstra算法
依最短路径的长度递增的次序求得各条路径。
设置一个集合S,该集合中存放从给定源点出发最短路径已知的所有顶点。
因此算法开始时,集合S中只有源点一个顶点。随着算法的进行,其余的顶点被逐步加入集合S。因此算法要解决的问题是确定每步应该加入哪个顶点?
设定一个数组int distance[graph_size];记录从源点到其它顶点的距离
若顶点v已在S中,则distance[v]记录了从源点到顶点v的最短距离。
若顶点v还未加入S中,则distance[v]记录了从源点到某个S中的顶点w的最短距离加上边<w,v>的权值。
distance数组的初始化。 (1)若从源点邻接到顶点v(有边的情况),则distance[v]即为该边的权值。(2)否则(无边的情况),则distance[v]为无穷大。
算法进行时,从distance中找一个最小值,并将其对应的顶点加入到S中。
一旦某顶点v加入S,则重新计算尚未加入S的顶点所对应的数组distance元素值。更新规则为:
若distance[w] > distance[v]+weight(<v,w>),
令 distance[w] = distance[v]+weight(<v,w>)
如此循环往复,直到把所有顶点加入S。
# include<stdio.h> # include<string.h> int map[160][160]; int flag[160]; int count[160]; char str[160][40]; int k; int dijkstra(int kk)//dijkstra算法 { int i,j,t,min; for(i=0;i<k;i++) { flag[i]=0; count[i]=map[kk][i]; } flag[kk]=1; count[kk]=0; for(i=0;i<k;i++) { min=1000000000; for(j=1;j<k;j++)//经过k次遍历,是足以遍历完的 { if(flag[j]==0&&count[j]<min) { min=count[j]; t=j; } } if(min==1000000000) break; flag[t]=1;//标记 for(j=0;j<k;j++)////更新 { if(flag[j]==0&&count[j]>count[t]+map[t][j]) count[j]=count[t]+map[t][j]; } } return count[1]; } int main() { int i,j,k1,k2,n,d; char str1[11000][40],str2[11000][40]; while(scanf("%d",&n),n!=-1) { for(i=0;i<155;i++) for(j=0;j<155;j++) map[i][j]=1000000000; scanf("%s%s",str1[0],str2[0]); strcpy(str[0],str1[0]); strcpy(str[1],str2[0]); k=2; for(i=1;i<=n;i++)//这种处理还是好理解的 { scanf("%s%s%d",str1[i],str2[i],&d); for(j=0;j<k;j++) { if(strcmp(str[j],str1[i])==0) { k1=j; break; } } if(j==k) { k1=j; strcpy(str[k],str1[i]); k++; } for(j=0;j<k;j++) { if(strcmp(str[j],str2[i])==0) { k2=j; break; } } if(j==k) { k2=j; strcpy(str[k],str2[i]); k++; } if(map[k1][k2]>d) map[k1][k2]=d; if(map[k2][k1]>d) map[k2][k1]=d; } if(strcmp(str1[0],str2[0])==0)//判断始点是否为终点 { printf("0\n"); continue; } else { d=dijkstra(0); if(d==1000000000) printf("-1\n"); else printf("%d\n",d); } } return 0; }