BOI 2002 双调路径

Posted OptimusPrime_L

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BOI 2002 双调路径相关的知识,希望对你有一定的参考价值。

题目:

城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用。路径由连续的道路组成。总时间是各条道路旅行时间的和,总费用是各条道路所支付费用的总和。同样的出发地和目的地,如果路径A比路径B所需时间少且费用低,那么我们说路径A比路径B好。对于某条路径,如果没有其他路径比它好,那么该路径被称为最优双调路径。这样的路径可能不止一条,或者说根本不存在。
给出城市交通网的描述信息,起始点和终点城市,求最优双条路径的条数。城市不超过100个,边数不超过300,每条边上的费用和时间都不超过100。

输入描述
第一行给出有多少个点,多少条边,开始点及结束点.

输出描述

有多少条双调路径

 
样例输入
4 5 1 4
2 1 2 1
3 4 3 1
2 3 1 2
3 1 1 4
2 4 2 4

样例输出 Sample Output

2 

分析:

本题用的一种巧妙的做法。显然这题是一道单源最短路问题,用SPFA或是Dijkstra都是可以的。但是我们要进行SPFA的是对于某个固定的花费下的所用的时间。也就是程序当中的dist[city][cost] = time这个在注释里有写。因为费用最大是100,所以cost开到二维数组开出来不会爆内存的!

本题有几个要注意的小问题:(有些是我愚蠢的错误)

  1. 因为是无向边Edge数组记得开2*MAXM
  2. 有的变量名字注意一下哈:time叫t,target也叫t,那不是很愚蠢啊……

程序:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN = 100 + 1;
 4 const int MAXM = 300 + 1;
 5 int n, m, s, t, EdgeCount = 0, MinTime = 0x3f3f3f3f, Head[MAXN];
 6 int dist[MAXN][MAXN*MAXN];
 7 bool vis[MAXN][MAXN*MAXN];
 8 struct edge
 9 {
10     int Next, Aim, Weight, Time;
11 }Edge[MAXM*2];
12 struct node
13 {
14     int pos, cost;
15 };
16 void insert(int u, int v, int w, int t)
17 {
18     Edge[++EdgeCount] = (edge){Head[u],v,w,t};
19     Head[u] = EdgeCount;
20 }
21 void SPFA()
22 {
23     memset(vis,false, sizeof(vis));
24     memset(dist, 0x3f, sizeof(dist));
25     //dist[city][cost] = time
26     queue<node> Q;
27     Q.push((node){s,0});
28     dist[s][0] = 0;
29     vis[s][0] = true;
30     while (!Q.empty())
31     {
32         node p = Q.front();
33         Q.pop();
34         //vis[p.pos][p.cost] = false;
35         if(p.cost > n*MAXN)
36             continue;
37         for (int i = Head[p.pos]; i; i = Edge[i].Next)
38         {
39             int v = Edge[i].Aim;
40             if(dist[v][p.cost + Edge[i].Weight] > dist[p.pos][p.cost] + Edge[i].Time)
41             {
42                 dist[v][p.cost+Edge[i].Weight] = dist[p.pos][p.cost] + Edge[i].Time;
43                 if(!vis[v][p.cost + Edge[i].Weight])
44                 {
45                     vis[v][p.cost + Edge[i].Weight] = true;
46                     Q.push((node){v,p.cost + Edge[i].Weight});
47                 }
48             }
49         }
50     }
51 }
52 int main()
53 {
54     memset(Head,0,sizeof(Head));
55     cin >> n >> m >> s >> t;
56     for (int i = 1; i <= m; i++)
57     {
58         int u, v, w, t;
59         cin >> u >> v >> w >> t;
60         insert(u,v,w,t);
61         insert(v,u,w,t);
62     }
63     SPFA();
64     int ans = 0;
65     for (int i = 0; i <= MAXN*n; i++)
66     {
67         //cout << dist[t][i] << endl;
68         if ((!(vis[t][i])) || dist[t][i] >= MinTime)
69             continue;
70         MinTime = dist[t][i];
71         ans++;
72     }
73     cout << ans << endl;
74     return 0;
75 }

 

以上是关于BOI 2002 双调路径的主要内容,如果未能解决你的问题,请参考以下文章

Bicriterial routing 双调路径 HYSBZ - 1375(分层最短路)

双调路径

双调旅行商问题 (Bitonic TSP)

算法导论-15-1-双调欧几里得旅行商问题

OpenCL 双调排序 GPU 版

OpenCL 双调排序 CPU 版