注意,dijkstra 是求最短路的一种方法, 可以算出一个单源点(起点),到图中任意一点的最短距离。
此题用dijkstra算法。
核心算法会记录每条路的距离,然后比较出最短的那条,然后从这条出发,继续和以前记录的比较,一直比较走到想走到的位置。
这一题还有一个技巧,题中给出几个起始点,dijkstra 只是起始点到终点的最短距离,所以按理说应该要调用几次dijkstra函数,不过题目给出了一个好的突破点,可以只调用一次。
题给出,1,2,... ,t 个起始点, 那么我们用map[0][1] = map[0][2] = ... = map[0][t] = 0 即可,则出发点就变为0了,而0到这些起始点的距离其实都为0 ,即没有。
#include<stdio.h>
#include<string.h>
const int INF = 10000000;
const int N = 1000+ 5;
int map[N][N],vis[N],lowcost[N]; //起始点到i点最小距离,用lowcost数组记录
void dijkstra(int n)
{
int pre ;
memset(vis,0,sizeof(vis)); //标记点数组初始化
for(int i = 1 ; i < N ; i++ )
lowcost[i] = INF;
vis[0] = 1; //别忘了这里
for(int i = 1 ; i <= n ; i++ )
lowcost[i] = map[0][i]; //给起始点到能连的点路径赋值
for(int i = 1 ; i <= n ; i++ )
{
int minn = INF;
for(int j = 1 ; j <= n ; j++ )
if(!vis[j]&&lowcost[j]<minn) // 记录到j点的最短距离
{
minn = lowcost[j] ;
pre = j;
}
vis[pre] = 1;
for(int k = 1 ; k <=n ; k++ ) //dijkstra算法核心思想
if(!vis[k]&&lowcost[k]>lowcost[pre]+map[pre][k]) //到k点的这个路径 和 到pre点的路径+pre和k之间的距离和比较
lowcost[k] = lowcost[pre]+map[pre][k];
}
}
int main()
{
int t,s,d,a,b,time;
int temp;
int ss[N],ee[N];
while(scanf("%d%d%d",&t,&s,&d)!=EOF)
{
temp = 0;
for(int i = 0 ; i < N ; i++ )
for(int j = 0 ; j < N ; j++ )
map[i][j] = INF; //初始化每条边无穷大
for(int i = 0 ; i < t ; i++ )
{
scanf("%d%d%d",&a,&b,&time); // a , b 之间可能有多条路,选短的那条
map[a][b] = map[a][b]>time?time:map[a][b];
map[b][a] = map[a][b] ;
if(a>temp) temp = a;
if(b>temp) temp = b; //temp 是记录最大的值,即我们最后能走到的那个点
}
for(int i = 0 ; i < s ; i++ )
{
int x ; scanf("%d",&x);
map[0][x] = 0; //前面说的技巧在这 多个起始点变成一个起始点
}
dijkstra(temp);
int ans = INF;
for(int i = 0 ; i < d ; i++ )
{
int y ; scanf("%d",&y);
ans = lowcost[y]<ans?lowcost[y]:ans;
}
printf("%d\n",ans);
}
return 0;
}