dijkstra及其相关练习题

来源:互联网 发布:淘宝网购物首页 编辑:程序博客网 时间:2024/06/03 01:41

dijkstra是用来求最短路的问题,就是给一张图,问从起始点到结束点的最短路径是多少。
出发点是第一个城市,目的地是第N个城市。

思路

做两个集合,一个集合中的元素是已经用过的城市,另一个集合的元素是未被用过的城市。
什么是用过的城市?什么又是没被用过的城市?
首先我们从第一个城市开始,遍历第二个,第三个…第N个城市,找到离第一个城市最近的。
然后我们把找到的这个最近的城市放在集合1中,这就是“用过”。
没在集合1中的城市自然就是“没用过”。
在我们找到这样一个城市后,然后以他为中转点,到其他城市
这样的话,我们就得到两条路,从第1个城市直接到第i个城市,还有从第1个城市先到这个中转城市,
再到第i个城市,然后取两者中最小值即可。
Dis[i] 表示从起始城市到第i个城市的最短距离
vis[i] = 0 or 1 , 1表示已经用过第i个城市,0表示还没用过。

实现代码:

for(i=1; i<=n; ++i)        {           min = INF;           for(j=1;j<=n;++j)             if(!vis[j] && d[j]<min)             {                min = d[j];                k=j;             }            vis[k] = 1;            for(j=1; j<=n; ++j)              if(!vis[j])                 if(d[j]>d[k]+p[k][j])                  d[j]=d[k]+p[k][j];        }

练习题

exercise1
Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。

Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间

Sample Input
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

Sample Output
3
2

代码:

#include<stdio.h>#include<string.h>const int INF = 999999;int d[105], p[105][105],vis[105],n,m;int main(){    int a,b,c;    int i,j,k;    int min;    while(scanf("%d%d",&n,&m)!=EOF && n+m)    {        for(i=1;i<=n;++i)            for(j=1; j<=n; ++j)                p[i][j] = INF;        for(i=0; i<m; ++i)        {            scanf("%d%d%d",&a,&b,&c);            p[a][b] = p[b][a] = c;        }        for(i=1; i<=n; ++i)            d[i] = INF;       d[1] = 0;       memset(vis, 0, sizeof(vis));       for(i=1; i<=n; ++i)        {           min = INF;           for(j=1;j<=n;++j)             if(!vis[j] && d[j]<min)             {                min = d[j];                k=j;             }            vis[k] = 1;            for(j=1; j<=n; ++j)              if(!vis[j])                 if(d[j]>d[k]+p[k][j])                  d[j]=d[k]+p[k][j];        }        printf("%d\n", d[n]);    }    return 0;}

exercise2:
Description
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。

Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。

Output
输出草儿能去某个喜欢的城市的最短时间。

Sample Input
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

Sample Output
9

代码:

#include<stdio.h>#include<string.h>#include<stdlib.h>int path[1005][1005];int dist[1005];int vis[1005];const int inf = 9999999;int main(){    int T,S,D;    int i,j,k;    int x,y,z;    int ans,from,to;    while(scanf("%d %d %d",&T,&S,&D)!=EOF)    {        memset(vis,0,sizeof(vis));        for(i=0;i<=1001;i++)           for(j=0;j<=1001;j++)               path[i][j] = inf;        for(i=0;i<=1001;i++)        {           path[i][i] = 0;           dist[i] = inf;        }        dist[0] = 0;        for(i=1;i<=T;i++)        {          scanf("%d%d%d",&x,&y,&z);          if(path[x][y]>z)            path[x][y] = path[y][x] = z;        }        for(i=1;i<=S;i++)        {           scanf("%d",&from);           path[0][from] = path[from][0] = 0;           dist[from] = 0;        }        for(i=0;i<=1001;i++)        {          ans = inf;          for(j=0;j<=1001;j++)          {            if(!vis[j] && dist[j]<ans)            {                ans = dist[j];                k = j;            }          }          vis[k] = 1;          for(j=0;j<=1001;j++)          {            if(!vis[j] && dist[j] > dist[k]+path[k][j])                dist[j] = dist[k] + path[k][j];          }       }       ans = inf;       for(i=1;i<=D;i++)       {          scanf("%d",&to);          if(dist[to]<ans)             ans = dist[to];       }       printf("%d\n",ans);    }       return 0;}

练习题3:
Description
Background
Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man who tells him whether there really is a way from the place his customer has build his giant steel crane to the place where it is needed on which all streets can carry the weight.
Fortunately he already has a plan of the city with all streets and bridges and all the allowed weights.Unfortunately he has no idea how to find the the maximum weight capacity in order to tell his customer how heavy the crane may become. But you surely know.

Problem
You are given the plan of the city, described by the streets (with weight limits) between the crossings, which are numbered from 1 to n. Your task is to find the maximum weight that can be transported from crossing 1 (Hugo’s place) to crossing n (the customer’s place). You may assume that there is at least one path. All streets can be travelled in both directions.
Input
The first line contains the number of scenarios (city plans). For each city the number n of street crossings (1 <= n <= 1000) and number m of streets are given on the first line. The following m lines contain triples of integers specifying start and end crossing of the street and the maximum allowed weight, which is positive and not larger than 1000000. There will be at most one street between each pair of crossings.
Output
The output for every scenario begins with a line containing “Scenario #i:”, where i is the number of the scenario starting at 1. Then print a single line containing the maximum allowed weight that Hugo can transport to the customer. Terminate the output for the scenario with a blank line.
Sample Input
1
3 3
1 2 3
1 3 4
2 3 5
Sample Output
Scenario #1:
4

代码:#include

#include <string.h>#define inf 9999999int p[1005][1005];int d[1005];int vis[1005];int main(){    int n,m,i,j,k,x,y,z,ans,cas,min,max,count=0;    scanf("%d",&cas);    while(cas--)    {        count++;        memset(vis,0,sizeof(vis));        memset(p,0,sizeof(p));        scanf("%d%d",&n,&m);        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&x,&y,&z);            p[x][y] = p[y][x] = z;        }        for(i=1;i<=n;i++)            d[i] = p[1][i];        d[1] = 0;        for(i=1;i<=n;i++)        {            k=0;            max = 0;            for(j=1;j<=n;j++)            {                if(!vis[j] && d[j]>max)                {                    max = d[j];                    k=j;                }            }            vis[k] = 1;            for(j=1;j<=n;j++)            {                if(!p[k][j])                    continue;                min = d[k];                if(d[k]>p[k][j])                    min = p[k][j];                if(d[j]<min)                    d[j] = min;            }        }        printf("Scenario #%d:\n",count);        if(cas)          printf("%d\n\n",d[n]);        else          printf("%d",d[n]);    }    return 0;}
0 0
原创粉丝点击