题目:
城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用。路径由连续的道路组成。总时间是各条道路旅行时间的和,总费用是各条道路所支付费用的总和。同样的出发地和目的地,如果路径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开到二维数组开出来不会爆内存的!
本题有几个要注意的小问题:(有些是我愚蠢的错误)
- 因为是无向边Edge数组记得开2*MAXM
- 有的变量名字注意一下哈: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 }