一个人的旅行(最短路+离散化)

http://acm.hdu.edu.cn/showproblem.php?pid=2066

一个人的旅行

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 23414    Accepted Submission(s): 8153


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
 

 

Author
Grass
 

 

Source
 

分析:求多个点之间的最短路,因为这个题的数据量1000所以Floyd会超时,考虑用多次Dijkstra,但是由于最后要统计出现的所有点的点数,这里新学的离散化,记下来

离散化的时候注意 是先将所有的点都储存下来再去除重复点,所以储存的数组要开的比他所给的点数多 (10*N ) run time error 了好多次,还要注意考虑去除重复边的情况,

考虑图不连通,考虑离散化的时候的点是按0~N-1编号的还是从1~N编号

下面给出代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<map>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<vector>
  7 using namespace std;
  8 #define INF 0x1fffffff
  9 #define N 1005
 10 #define M 2000005
 11 struct Edge{
 12     int to;
 13     int v ;
 14     int next;
 15 }edge[M];
 16 int Enct;
 17 int head[N];
 18 void add(int from ,int to , int v )
 19 {
 20     edge[Enct].to = to ;
 21     edge[Enct].v = v ;
 22     edge[Enct].next = head[from];
 23     head[from] = Enct++;
 24 
 25     edge[Enct].to = from ;
 26     edge[Enct].v = v ;
 27     edge[Enct].next = head[to];
 28     head[to] = Enct++;
 29 }
 30 void init ()
 31 {
 32     Enct = 0;
 33     memset(head,-1, sizeof(head));
 34 }
 35 int dist[N];
 36 bool p[N];
 37 void dijk(int s, int n)
 38 {
 39     int i , j , k ;
 40     for( i = 1 ;  i <= n ; i++ )
 41     {
 42         p[i] = false;
 43         dist[i]= INF;
 44     }
 45     p[s] = true;
 46     dist[s] = 0;
 47     for( i = head[s] ; i != -1 ; i = edge[i].next)
 48     {
 49         Edge e = edge[i];
 50         if(e.v<dist[e.to])//考虑重边
 51         dist[e.to] = e.v;
 52     }
 53     for( i = 1 ;i < n ;i++)
 54     {
 55         int Min = INF;
 56         int k = 0 ;
 57         for( j = 1 ; j <= n ; j++)
 58         {
 59             if(!p[j]&&dist[j]<Min)
 60             {
 61                 Min = dist[j];
 62                 k = j;
 63             }
 64         }
 65         p[k] = true;
 66         if(Min == INF) return ;
 67         for( j = head[k] ;j!=-1 ;j=edge[j].next)
 68         {
 69             Edge e = edge[j];
 70             if(!p[e.to]&&dist[e.to]>dist[k]+e.v)
 71             {
 72                 dist[e.to] = dist[k]+e.v;
 73             }
 74         }
 75     }
 76 }
 77 vector <int> sss;
 78 vector <int> ttt;
 79 map <int ,int> mp;
 80 vector<int>::iterator sj;
 81 vector<int>::iterator tj;
 82 int city[10*N], city_cnt; //city有可能有重点,所以数组要开大一点,防止越界
 83 struct Node
 84 {
 85     int s, t, l;
 86 }nd[M];
 87 int main()
 88 {
 89     int t , w , l ;
 90     while(~scanf("%d%d%d",&t,&w,&l))
 91     {
 92         city_cnt = 0;
 93         int tt, ww,ll;
 94         init();
 95         for(int i = 0 ;i < t ; i++)
 96         {
 97             //scanf("%d%d%d",&tt,&ww,&ll);
 98             scanf("%d%d%d",&nd[i].s,&nd[i].t,&nd[i].l);
 99             city[city_cnt++] = nd[i].s;
100             city[city_cnt++] = nd[i].t;
101             //add(tt,ww,ll);
102         }
103         int mmm = INF ;
104         sss.clear();//初始化
105         for(int i = 0 ;i < w ; i++)
106         {
107             int ss;
108             scanf("%d",&ss);
109             city[city_cnt++] = ss;
110             sss.push_back(ss);
111         }
112         ttt.clear();
113         for(int i = 0 ; i < l ; i++)
114         {
115             int zd;
116             scanf("%d",&zd);
117             city[city_cnt++] = zd;
118             ttt.push_back(zd);
119         }
120         sort(city, city+city_cnt);//离散化
121         city_cnt = unique(city, city+city_cnt)-city;//去重
122         mp.clear();
123         for(int i = 0; i< city_cnt; i++) mp[city[i]] = i+1;
124 
125         for(int i = 0; i < t; i++) {
126                 add(mp[nd[i].s], mp[nd[i].t], nd[i].l);
127                 //printf("%d %d %d\n", mp[nd[i].s], mp[nd[i].t], nd[i].l);
128         }
129 
130         for(sj = sss.begin(); sj!=sss.end();sj++)
131         {
132             dijk(mp[(*sj)],city_cnt);
133             //printf("%d:\n", (*sj));
134             //for(int i = 1; i <= city_cnt; i++) printf("%d ", dist[i]); puts("");
135             for(tj = ttt.begin(); tj!=ttt.end(); tj++)
136             {
137 
138                 if(mmm > dist[mp[(*tj)]])
139                     mmm = dist[mp[(*tj)]];
140             }
141         }
142         printf("%d\n",mmm);
143     }
144     return 0;
145 }

 

 

转载于:https://www.cnblogs.com/shanyr/p/4670206.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值