1,算法步骤:
a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。
b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
d.重复步骤b和c直到所有顶点都包含在S中。
2,说的很抽象,我也不是很理解,多做几道模板题,会慢慢理解的!
A - 温习最短路1
Description
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
Sample Output
2 -1
是模板题,可自己不会做,学长的代码,自己加上注释,以便日后理解,随后会贴上自己写的Dijkstra 算法题的代码!
现在先纪念一下:
#include<stdio.h>
#include<string.h>
#define MAX 99999
int n,m ,i,j,k;
int map[1007][1007];//代表两点之间的距离
int visit[1007];//代表节点是否被访问过
int dis[1007];//代表两点之间的距离
int dijstra(int x,int y)//x代表起点,y代表终点
{
int min;
memset(visit,0,sizeof(visit));//开始都没访问
for(i=0;i<n;i++)//这一个for循环的作用是初始化,从主函数调过来
{
dis[i]=map[x][i];//让dis[]默认的,为节点到起点的距离
}
dis[x]=0;//起点到起点的距离是0
visit[x]=1;//起点被访问过,标记为1
for(i=0;i<n;i++)//遍历所有的节点
{
min=MAX;
for(j=0;j<n;j++)//这一个for循环的作用是,从起点开始,遍历所有的节点
{
if(!visit[j]&&dis[j]<min)//所有没访问的,并且距离最短的,则节点之间的距离就更新
{
min=dis[j];
k=j;//并把访问的节点标记下来
}
}
visit[k]=1;//代表已访问
for(j=0;j<n;j++)//这一个for循环的作用是,从第一个for循环得到的,离起点最短的节点开始,遍历所有的节点
{
if(!visit[j]&&dis[j]>min+map[k][j]) //比较
//k是起点,j是终点 //起点到第三个点的直接距离
//与
//上一个for循环得到起点到第2个节点最短距离+第2个节点与第3个节点距离
//最小值
{
dis[j]=min+map[k][j];
}
}
}
return dis[y];
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<n;i++)//这一个for循环的作用是初始化,让所有两点之间的距离无穷大
{
for(j=0;j<n;j++)
{
map[i][j]=map[j][i]=MAX;
}
}
while(m--)
{
int a,b,distance;
scanf("%d%d%d",&a,&b,&distance);//更新两点之间的距离
if(map[a][b]>distance)
{
map[a][b]=map[b][a]=distance;
}
}
int begin,end;
scanf("%d%d",&begin,&end);
int ans=dijstra(begin,end);
if(ans==MAX)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}
这是自己做的,因为和上一题类似,所以思路,代码都差不多
B - 温习最短路2
Description
Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible.
Farmer John's field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1..N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it.
Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.
Input
* Line 1: Two integers: T and N
* Lines 2..T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1..100.
Output
Sample Input
5 5 1 2 20 2 3 30 3 4 20 4 5 20 1 5 100
Sample Output
90
Hint
There are five landmarks.
OUTPUT DETAILS:
Bessie can get home by following trails 4, 3, 2, and 1.
#include<stdio.h>
#include<string.h>
#define MAX 99999
int visit[1007],dis[1007],map[1007][1007];
int i,j,k,m,n,t;
int Dijkstra(int s,int e)
{
int min;
memset(visit,0,sizeof(visit));
for(i=1;i<=n;i++)
{
dis[i]=map[s][i];
}
dis[s]=0;
visit[s]=1;
for(i=1;i<=n;i++)
{
min=MAX;
for(j=1;j<=n;j++)
{
if(!visit[j]&&dis[j]<min)
{
min=dis[j];
k=j;
}
}
visit[k]=1;
for(j=1;j<=n;j++)
{
if(!visit[j]&&dis[j]>min+map[k][j])
{
dis[j]=min+map[k][j];
}
}
}
return dis[e];
}
int main()
{
while(scanf("%d%d",&t,&n)==2)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
map[i][j]=map[j][i]=MAX;
}
}
while(t--)
{
int a,b,distance;
scanf("%d%d%d",&a,&b,&distance);
if(map[a][b]>distance)
map[a][b]=map[b][a]=distance;
}
int ans=Dijkstra(1,n);
printf("%d\n",ans);
}
return 0;
}
这也是模板题,重在熟悉,理解
最短路
输入保证至少存在1条商店到赛场的路线。
2 1 1 2 3 3 3 1 2 5 2 3 5 3 1 2 0 0
3 2
#include<stdio.h>
#include<string.h>
#define MAX 99999
int visit[1007],dis[1007],map[1007][1007];
int i,j,k,m,n;
int dijkstra(int s,int e)
{
int min;
memset(visit,0,sizeof(visit));
for(i=1;i<=n;i++)
{
dis[i]=map[s][i];
}
dis[s]=0;
visit[s]=1;
for(i=1;i<=n;i++)
{
min=MAX;
for(j=1;j<=n;j++)
{
if(!visit[j]&&dis[j]<min)
{
min=dis[j];
k=j;
}
}
visit[k]=1;
for(j=1;j<=n;j++)
{
if(!visit[j]&&dis[j]>min+map[k][j])
dis[j]=min+map[k][j];
}
}
return dis[e];
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(m==0&&n==0)
return 0;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
map[i][j]=map[j][i]=MAX;
}
}
while(m--)
{
int a,b,distance;
scanf("%d%d%d",&a,&b,&distance);
if(map[a][b]>distance)
{
map[a][b]=map[b][a]=distance;
}
}
int ans=dijkstra(1,n);
printf("%d\n",ans);
}
return 0;
}
这道题与之前的有不一样,没有给出起点和终点,其实一次dijkstra即可,我们将草儿家看成0,从家到相邻的时间看成0,我们只需求家到各个目的地的最短距离即可
一个人的旅行
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
6 2 3 1 3 5 1 4 7 2 8 12 3 8 4 4 9 12 9 10 2 1 2 8 9 10
9
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int inf = 1<<30;
int T,S,D,n;
int map[1111][1111];
int vis[1111],cast[1111];
int s[1111],e[1111];
void Dijkstra()
{
int i,j,minn,pos;
memset(vis,0,sizeof(vis));
vis[0] = 1;
for(i = 0; i<=n; i++)
cast[i] = map[0][i];
for(i = 1; i<=n; i++)
{
minn = inf;
for(j = 1; j<=n; j++)
{
if(cast[j]<minn && !vis[j])
{
pos = j;
minn = cast[j];
}
}
vis[pos] = 1;
for(j = 1; j<=n; j++)
{
if(cast[pos]+map[pos][j]<cast[j] && !vis[j])
cast[j] = cast[pos]+map[pos][j];
}
}
}
int main()
{
int i,j,x,y,z,start,end;
while(scanf("%d%d%d",&T,&S,&D))
{
n = 0;
for(i = 0; i<1111; i++)
{
for(j = 0; j<1111; j++)
map[i][j] = inf;
}
while(T--)
{
scanf("%d%d%d",&x,&y,&z);
n = max(max(n,x),y);
if(z<map[x][y])
map[x][y] = map[y][x] = z;
}
int minn = inf;
for(i = 0; i<S; i++)
{
scanf("%d",&s[i]);
map[0][s[i]] = map[s[i]][0] = 0;
}
for(i = 0; i<D; i++)
scanf("%d",&e[i]);
Dijkstra();
for(i = 0; i<D; i++)
minn = min(minn,cast[e[i]]);
printf("%d\n",minn);
}
return 0;
}