一个人的旅行
2015-08-18 22:42
225 查看
Problem 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
注意:注意有多个起始点,多个终点,且每2点间路不唯一,所以要考虑重边。采用加入超级源点的做法时,必须建立一个邻接表,并且初始化时的方式与模板不一样。
法一:Dijkstra+加入超级源点
法三:SPAF+超级源点
下面的这个代码超时,不知道为什么!!!
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^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
注意:注意有多个起始点,多个终点,且每2点间路不唯一,所以要考虑重边。采用加入超级源点的做法时,必须建立一个邻接表,并且初始化时的方式与模板不一样。
法一:Dijkstra+加入超级源点
<span style="font-size:18px;">#include<stdio.h> #include<string.h> //#define MIN(a,b) a<b?a:b //#define MAX(c,d) c>d?c:d #define MIN(a,b) (a<b?a:b)//没加括号之前,结果一直是0,加了括号之后,正确结果出来了。 #define MAX(c,d) (c>d?c:d) #define INF 0x3f3f3f int cost[1100][1100]; int d[1100]; int mark[1100]; int n;//n的值不确定 void dijkstra(int t) { int u,i,j; for(i=0;i<=n;i++) { mark[i]=0; d[i]=cost[t][i];//第一步初始化,用加入超级源点的方法的初始化是这样的! //d[i]=INF;不用加入超级源点的方法的初始化时这样的,注意区分! } d[t]=0; while(1) { int v=-1; for(u=0;u<=n;u++) { if(mark[u]==0&&(v==-1||d[u]<d[v])) v=u;//每次都写成u=v;花了好长时间才找出来 } if(v==-1) break; mark[v]=1; for(u=0;u<=n;u++) d[u]=MIN(d[u],d[v]+cost[v][u]); } } int main() { int T,S,D,i,j,a,b,c; while(scanf("%d%d%d",&T,&S,&D)!=EOF) { //for(i=1;i<1001;i++) // for(j=1;j<1001;j++) // cost[i][j]=INF; for(i=0;i<1001;i++)//题目中若没有要求的话,最好从0开始初始化 ,并且注意前后一致。 for(j=0;j<=1001;j++) cost[i][j]=INF; while(T--) { scanf("%d%d%d",&a,&b,&c); n=MAX(n,MAX(a,b));//n取输入的编号中最大的 if(c<cost[a][b]) cost[a][b]=cost[b][a]=c; } int p,k; while(S--) { scanf("%d",&p); cost[0][p]=cost[p][0]=0;//把多个起点变成了一个起点。 } dijkstra(0);//现在0是惟一的起点 int min=INF; while(D--) { scanf("%d",&k); // dijkstra(0); if(min>d[k]) min=d[k]; } printf("%d\n",min); } return 0; </span>}
<span style="font-size:18px;color:#ff6600;">法二:Dijkstra按照模板的做法来写</span>
<span style="font-size:18px;color:#ff6600;"></span>
<span style="font-size:18px;">#include<stdio.h> #include<string.h> #define INF 0xfffffff #define MAX(a,b) (a>b?a:b) #define MIN(a,b) (a<b?a:b) int cost[1100][1100]; int d[1100]; int mark[1100]; int n; void dijkstra(int t) { int i,j; // for(i=0;i<n;i++)从0开始编号的话应该是i<=n!!! for(i=0;i<=n;i++) //n是最后一个城市的编号 { d[i]=INF; mark[i]=0; } d[t]=0; while(1) { int v=-1; for(int u=0;u<=n;u++) { if(mark[u]==0&&(v==-1||d[u]<d[v])) v=u; } if(v==-1) break; mark[v]=1; for(int u=0;u<=n;u++) d[u]=MIN(d[u],d[v]+cost[v][u]); } } int main() { int T,S,D; while(scanf("%d%d%d",&T,&S,&D)!=EOF) { int i,j; n=0; for(i=0;i<1001;i++) for(j=0;j<1001;j++) cost[i][j]=INF; while(T--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); n=MAX(n,MAX(a,b)); if(c<cost[a][b]) cost[a][b]=cost[b][a]=c; } int s[1100]; int want[1100]; for(i=0;i<S;i++) scanf("%d",&s[i]); for(i=0;i<D;i++) scanf("%d",&want[i]); int min=INF; for(i=0;i<S;i++)//这个是难点 { dijkstra(s[i<span style="color:#ff0000;">]);//优化的地方!!!若每两个点调用一次dijkstra函数,会超时</span>。 for(j=0;j<D;j++) { if(min>d[want[j]]) min=d[want[j]]; } } printf("%d\n",min); } return 0; } </span>
法三:SPAF+超级源点
#include<stdio.h> #include<string.h> #include<queue> #include<algorithm> #define max(a,b) a>b?a:b #define MAX 1100 #define INF 0x3f3f3f int edgenum; using namespace std; int d[MAX]; int mark[MAX]; int head[MAX]; int T,S,D,n; struct Edge { int from,to,val,next; }edge[MAX*10]; void addedge(int u,int v,int w) { Edge E={u,v,w,head[u]}; edge[edgenum]=E; head[u]=edgenum++; } void SPFA(int sx) { memset(mark,0,sizeof(mark)); memset(d,INF,sizeof(d)); queue<int>q; q.push(sx); mark[sx]=1; d[sx]=0; while(!q.empty()) { int u=q.front(); q.pop(); mark[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(d[v]>d[u]+edge[i].val) { d[v]=d[u]+edge[i].val; if(mark[v]==0) { q.push(v); mark[v]=1; } } } } } int main() { while(scanf("%d%d%d",&T,&S,&D)!=EOF) { int i,j; int a,b,c,s,want; edgenum=0; memset(head,-1,sizeof(head)); while(T--) { scanf("%d%d%d",&a,&b,&c); n=max(n,max(a,b)); addedge(a,b,c);//注意建双向边 addedge(b,a,c); } while(S--) { scanf("%d",&s); addedge(0,s,0);//注意建双向边 addedge(s,0,0); } SPFA(0); int min=INF; for(i=0;i<D;i++) { scanf("%d",&want); if(d[want]<min) { min=d[want]; } } printf("%d\n",min); } return 0; }
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span>
下面的这个代码超时,不知道为什么!!!
#include<stdio.h> #include<string.h> #include<queue> #include<algorithm> #define INF 0x3f3f3f #define MAX 1000 #define max(a,b) (a>b?a:b) using namespace std; int T,S,D,n; int d[MAX]; int s[MAX]; int want[MAX]; int head[MAX]; int mark[MAX]; int edgenum; struct Edge { int from,to,val,next; }edge[MAX*2]; void addedge(int u,int v,int w) { Edge E={u,v,w,head[u]}; edge[edgenum]=E; head[u]=edgenum++; } void SPFA(int sx) { for(int i=0;i<=n;i++)//i<=n ,易错点 n是城市的最大编号 { mark[i]=0; d[i]=INF; } queue<int>q; q.push(sx); mark[sx]=1; d[sx]=0; while(!q.empty()) { int u=q.front(); q.pop(); mark[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(d[v]>d[u]+edge[i].val) { d[v]=d[u]+edge[i].val; if(mark[v]==0) { q.push(v); mark[v]=1; } } } } } int main() { while(scanf("%d%d%d",&T,&S,&D)!=EOF) { int i,j; int a,b,c; // memset(mark,0,sizeof(mark)); // memset(d,INF,sizeof(d)); memset(head,-1,sizeof(head)); // for( i=0;i<n;i++) // head[i]=-1; edgenum=0; while(T--) { scanf("%d%d%d",&a,&b,&c); n=max(n,max(a,b)); addedge(a,b,c); addedge(b,a,c); } for(i=0;i<S;i++) scanf("%d",&s[i]); for(i=0;i<D;i++) scanf("%d",&want[i]); int min=INF; for(i=0;i<S;i++) { SPFA(s[i]); for(j=0;j<D;j++) { if(d[want[j]]<min) min=d[want[j]]; } } printf("%d\n",min); } return 0; }
相关文章推荐
- 面试题总结
- C#程序开发中经常遇到的10条实用的代码
- 自定义Notification~~
- 使用OpenCv with Android Camera Surfaceview时OpenCVLoader失败问题
- netty学习(二)--传统的bio编程
- BA-siemens-insight报警设置
- jsp页面放在webroot下与放在WEB-INF的区别
- yum安装
- 全排列 (深搜 DFS)
- dhtmlx中,在window窗口底部添加状态栏(StatusBar)显示表格分页
- C语言相关知识点
- Linux添加/删除用户和用户组
- Android之GPU过度绘制与图形渲染优化——Hierarchyviewer时间不显示
- C_无符号数和有符号数的左移和右移
- VB6.0 SP6 AOD应用笔记——第一部分
- 三大框架之hibernate教程入门1
- OpenGL背面剔除
- 2015第34周二能收发邮件但不能打开网页解决方法
- hdu 1846 Brave Game (巴什博弈)
- C++垃圾回收器的实现