HDU2680 - Choose the best route - 最短路(多起点集合)

1.题目描述:

Choose the best route

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 14192    Accepted Submission(s): 4641


Problem Description
One day , Kiki wants to visit one of her friends. As she is liable to carsickness , she wants to arrive at her friend’s home as soon as possible . Now give you a map of the city’s traffic route, and the stations which are near Kiki’s home so that she can take. You may suppose Kiki can change the bus at any station. Please find out the least time Kiki needs to spend. To make it easy, if the city have n bus stations ,the stations will been expressed as an integer 1,2,3…n.
 

Input
There are several test cases. 
Each case begins with three integers n, m and s,(n<1000,m<20000,1=<s<=n) n stands for the number of bus stations in this city and m stands for the number of directed ways between bus stations .(Maybe there are several ways between two bus stations .) s stands for the bus station that near Kiki’s friend’s home.
Then follow m lines ,each line contains three integers p , q , t (0<t<=1000). means from station p to station q there is a way and it will costs t minutes .
Then a line with an integer w(0<w<n), means the number of stations Kiki can take at the beginning. Then follows w integers stands for these stations.
 

Output
The output contains one line for each data set : the least time Kiki needs to spend ,if it’s impossible to find such a route ,just output “-1”.
 

Sample Input
  
  
5 8 5 1 2 2 1 5 3 1 3 4 2 4 7 2 5 6 2 3 5 3 5 1 4 5 1 2 2 3 4 3 4 1 2 3 1 3 4 2 3 2 1 1
 

Sample Output
  
  
1 -1
 

Author
dandelion
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   2066  1142  1385  2923  1690 
2.题意概述:

题目大意就是一个人坐公交车晕车,要找到时间最少的路线。

测试数据意思:
第一行三个数:n(车站的个数,n<1000)  |  m(代表车站之间所有线路的总个数)  | s(代表离朋友家最近的车站)
下面有m行:   p q t   意思是:一条从p到q的线路,花费t时间
m行之后有个数字:w (代表可以在开始时搭乘的车站)
下面w个数W1,W2....Ww就是车站的编号

3.解题思路:

多起点的最短路一种做法是变终点为起点,变起点为终点,最后更新一下最小值。

第二种做法是增加一个‘0’起点到所有起点集合距离为0,那么只需要求0到终点的距离就好。

4.AC代码:

我一样拍的是dijkstra,一种做法是优先队列+邻接表,这题其实有个可以优化的地方是,多条公交线路,那么肯定是乘坐最优的,直接邻接矩阵更新最小值就好(也是码完对比 时间发现n方的优化居然比堆耗时更低)

01 - dijkstra + 堆优化

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 20100
#define N 11111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
struct node
{
	int to, val;
	node(int a, int b) { to = a; val = b; }
	friend bool operator< (node a, node b)
	{
		return a.val < b.val;
	}
};
vector <node> mp[N];
int dis[N];
void dijkstra(int sta, int ed)
{
	fill(dis, dis + ed, INF);
	priority_queue<node> q;
	dis[sta] = 0;
	q.push(node(sta, 0));
	while (!q.empty())
	{
		int u = q.top().to;
		q.pop();
		int sz = mp[u].size();
		for (int i = 0; i < sz; i++)
		{
			int v = mp[u][i].to;
			int val = mp[u][i].val;
			if (dis[v] > dis[u] + val)
				q.push(node(v, dis[v] = dis[u] + val));
		}
	}
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	long _begin_time = clock();
#endif
	int n, m, s;
	while (~scanf("%d%d%d", &n, &m, &s))
	{
		for (int i = 0; i <= n; i++)
			mp[i].clear();
		for (int i = 0; i < m; i++)
		{
			int p, q, t;
			scanf("%d%d%d", &p, &q, &t);
			mp[p].push_back(node(q, t));
		//	mp[q].push_back(node(p, t));
		}
		int w;
		scanf("%d", &w);
		while (w--)
		{
			int x;
			scanf("%d", &x);
			mp[0].push_back(node(x, 0));
		}
		dijkstra(0, n + 1);
		printf("%d\n", dis[s] == INF ? -1 : dis[s]);
	}
#ifndef ONLINE_JUDGE
	long _end_time = clock();
	printf("time = %ld ms.", _end_time - _begin_time);
#endif
	return 0;
}

02 - dijkstra + 邻接矩阵

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 11111
#define eps 1e-6
#define pi acos(-1.0)
#define e 2.718281828459
#define mod (int)1e9 + 7
using namespace std;
typedef long long ll;
int mp[maxn][maxn], vis[maxn], dis[maxn];
void init(int n)
{
  memset(vis, 0, sizeof(vis));
  memset(dis, INF, sizeof(dis));
  for (int i = 0; i <= n; i++)
    for (int j = 0; j <= n; j++)
      if (i == j)
        mp[i][j] = 0;
      else
        mp[i][j] = INF;
}
void dijkstra(int ed, int sta)
{
  dis[sta] = 0;                 // 标记起点
  for (int i = 0; i <= ed; i++) //从起点到终点
  {
    int x = sta, tmp = INF;
    for (int j = 0; j <= ed; j++)
      if (!vis[j] && dis[j] < tmp)
      {
        tmp = dis[j]; //更新最小值
        x = j;        //记录走到哪
      }
    if (tmp == INF) //不通
      break;
    vis[x] = 1; //走过的路标记
    for (int j = 0; j <= ed; j++)
      if (dis[j] > dis[x] + mp[x][j])
        dis[j] = dis[x] + mp[x][j];
  }
}
int main()
{
#ifndef ONLINE_JUDGE
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
  long _begin_time = clock();
#endif
  int n, m, d;
  while (~scanf("%d%d%d", &n, &m, &d))
  {
    init(n);
    int u, v, w;
    for (int i = 0; i < m; i++)
    {
      scanf("%d%d%d", &u, &v, &w);
      if (w < mp[u][v])
        mp[u][v] = w;
    }
    int num, pos;
    scanf("%d", &num);
    for (int i = 0; i < num; i++) //自己加一个
    {
      scanf("%d", &pos);
      mp[0][pos] = 0;
    }
    dijkstra(n, 0);
    if (dis[d] != INF)
      printf("%d\n", dis[d]);
    else
      puts("-1");
  }

#ifndef ONLINE_JUDGE
  long _end_time = clock();
  printf("time = %ld ms.", _end_time - _begin_time);
#endif
  return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值