HDU 2066 一个人的旅行 <裸的迪杰斯特拉算法+虚拟顶点法>
2015-08-18 19:27
459 查看
一个人的旅行
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 24776 Accepted Submission(s): 8592
[align=left]Problem Description[/align]
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
[align=left]Input[/align]
输入数据有多组,每组的第一行是三个整数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个数,表示草儿想去地方。
[align=left]Output[/align]
输出草儿能去某个喜欢的城市的最短时间。
[align=left]Sample Input[/align]
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
[align=left]Sample Output[/align]
9
[align=left]Author[/align]
Grass
[align=left]Source[/align]
RPG专场练习赛
思路:
这道题和以前做的题唯一的不同就是给你的起点和终点的个数不是一个了,让你选一个起点到其中一个终点之间距离最短的路,输出最小的长度!所以你要遍历所有的起点到所有的终点的距离,选择一个最短的距离,将其输出!
并且这道题的点的范围也没有给你,所以你要通过标胶来确定一个范围,然后才能用迪杰特斯拉算法!
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f int map[1005][1005]; int dis[1005]; int vis[1005]; int T,S,D; int x[1005]; int y[1005]; int z1,z2; void init() { int a,b,c; z1=INF,z2=0; memset(map,INF,sizeof(map)); for(int i=1;i<=T;i++) { scanf("%d%d%d",&a,&b,&c); z1=z1>a?a:z1;//最小的点 z1=z1>b?b:z1; z2=z2>a?z2:a;// 最大的点! z2=z2>b?z2:b; if(c<map[a][b])//要是重复输入一条路,要选花费时间小的! map[a][b]=map[b][a]=c; } for(int i=1;i<=S;i++) scanf("%d",&x[i]); for(int i=1;i<=D;i++) scanf("%d",&y[i]); } void dijkstra(int x) { memset(vis,0,sizeof(vis)); for(int i=z1;i<=z2;i++) { dis[i]=map[x][i]; } dis[x]=0; vis[x]=1; int min,k; for(int i=z1;i<=z2;i++) { min=INF; for(int j=z1;j<=z2;j++) { if(!vis[j]&&dis[j]<min) { min=dis[j]; k=j; } } if(min==INF)//这是两个等号,一定不能忘!!!!!!!!! break; vis[k]=1; for(int j=z1;j<=z2;j++) { if(!vis[j]&&dis[j]>dis[k]+map[k][j]) { dis[j]=dis[k]+map[k][j]; } } } } int main() { while(scanf("%d%d%d",&T,&S,&D)!=EOF) { int min=INF; init(); for(int i=1;i<=S;i++) { dijkstra(x[i]); for(int j=1;j<=D;j++) { min=min>dis[y[j]]?dis[y[j]]:min; } } printf("%d\n",min); } return 0; }
虚拟顶点的代码:
//迪杰斯特拉+虚拟顶点法 //起点虚拟为最小的点减1,终点虚拟为最大的点加1,起点和终点都是唯一的,直接迪杰斯特大就行了! #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f int m,S,D; int map[1005][1005]; int vis[1005]; int dis[1005]; int tx,ty; void init() { memset(map,INF,sizeof(map)); memset(dis,INF,sizeof(dis)); int a,b,c; tx=INF,ty=0; for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); tx=tx>a?a:tx; tx=tx>b?b:tx; ty=ty>a?ty:a; ty=ty>b?ty:b; if(map[a][b]>c) map[a][b]=map[b][a]=c; } for(int i=1;i<=S;i++) { scanf("%d",&a);//只有给的起点和虚拟起点距离为0,其他的点和起点的距离为INF dis[a]=map[tx-1][a]=map[a][tx-1]=0;//要么写成双向边,要么写成map[tx-1][a]=0; } for(int j=1;j<=D;j++) { scanf("%d",&a);//只有终点和虚拟终点之间的距离为0,其他的点和终点的距离为INF map[ty+1][a]=map[a][ty+1]=0;//这一点记住不要写成map[ty+1][a],这样是错的! }//要么写成双向边,要么写成map[a][ty+1]=0; } void dij() { memset(vis,0,sizeof(vis)); int min,k; for(int i=tx;i<=ty+1;i++) { min=INF; for(int j=tx;j<=ty+1;j++) { if(!vis[j]&&min>dis[j]) { min=dis[j]; k=j; } } if(min==INF) { break; } vis[k]=1; for(int j=tx;j<=ty+1;j++) { if(!vis[j]&&dis[j]>dis[k]+map[k][j]) { dis[j]=dis[k]+map[k][j]; } } } printf("%d\n",dis[ty+1]); } int main() { while(scanf("%d%d%d",&m,&S,&D)!=EOF) { init(); dij(); } return 0; }
相关文章推荐
- hdoj 2680 Choose the best route 【dijkstra】
- mac 下的 vi 指令
- Travelling Salesman Problem (hdu 5402 模拟)
- 引用
- 安装Apache的时候80端口被PID为4的系统进程所占用
- OC笔记NSDate
- 相同的 birthday
- 中文ubuntu里用户目录里的路径改成英文
- MySQL备份
- 设计模式交流有感
- 贪心算法专题小结——区间相关问题
- 解决Dialog 消失,输入法不消失的问题
- Activity生命周期
- IOS-TextField控件详解
- 将输入的字符串(字符串仅包含小写字母‘a’到‘z’),按照如下规则,循环转换后输出:a->b,b->c,…,y->z,z->a;若输入的字符串连续出现两个字母相同时,后一个字母需要连续转换2次。例如:
- 自定义异常类一
- fanqiang
- python视频教程大全集下载啦!超级全的教程!
- Dream------spark--spark集群的环境搭建
- Fragment 实现tab页卡切换并保存界面状态,动态添加Fragment