1018. Public Bike Management (30)-PAT甲级真题(Dijkstra + DFS)

There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.

The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.

When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.

Snip20160825_77
Figure 1 illustrates an example. The stations are represented by vertices and the roads correspond to the edges. The number on an edge is the time taken to reach one end station from another. The number written inside a vertex S is the current number of bikes stored at S. Given that the maximum capacity of each station is 10. To solve the problem at S3, we have 2 different shortest paths:

1. PBMC -> S1 -> S3. In this case, 4 bikes must be sent from PBMC, because we can collect 1 bike from S1 and then take 5 bikes to S3, so that both stations will be in perfect conditions.

2. PBMC -> S2 -> S3. This path requires the same time as path 1, but only 3 bikes sent from PBMC and hence is the one that will be chosen.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 numbers: Cmax (<= 100), always an even number, is the maximum capacity of each station; N (<= 500), the total number of stations; Sp, the index of the problem station (the stations are numbered from 1 to N, and PBMC is represented by the vertex 0); and M, the number of roads. The second line contains N non-negative numbers Ci (i=1,…N) where each Ci is the current number of bikes at Si respectively. Then M lines follow, each contains 3 numbers: Si, Sj, and Tij which describe the time Tij taken to move betwen stations Si and Sj. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print your results in one line. First output the number of bikes that PBMC must send. Then after one space, output the path in the format: 0->S1->…->Sp. Finally after another space, output the number of bikes that we must take back to PBMC after the condition of Sp is adjusted to perfect.

Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC. The judge’s data guarantee that such a path is unique.

Sample Input:
10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
Sample Output:
3 0->2->3 0
题目大意:每个自行车车站的最大容量为一个偶数cmax,如果一个车站里面自行车的数量恰好为cmax / 2,那么称处于完美状态。如果一个车站容量是满的或者空的,控制中心(处于结点0处)就会携带或者从路上收集一定数量的自行车前往该车站,一路上会让所有的车站沿途都达到完美。现在给出cmax,车站的数量n,问题车站sp,m条边,还有距离,求最短路径。如果最短路径有多个,求能带的最少的自行车数目的那条。如果还是有很多条不同的路,那么就找一个从车站带回的自行车数目最少的(带回的时候是不调整的)~
分析:Dijkstra + DFS。如果只有Dijkstra是不可以的,因为minNeed和minBack在路径上的传递不满足最优子结构,不是简单的相加的过程,只有在所有路径都确定了之后才能区选择最小的need和最小的back~
Dijkstra求最短路径,dfs求minNeed和minBack和path,dfs的时候模拟一遍需要调整的过程,求出最后得到的need和back,与minNeed和minBack比较然后根据情况更新path,最后输出minNeed path 和 minBack,记得path是从最后一个结点一直到第一个结点的,所以要倒着输出~

L3-005. 垃圾箱分布-PAT团体程序设计天梯赛GPLT(Dijkstra)

大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。

现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。

输入格式:

输入第一行给出4个正整数:N(<= 103)是居民点的个数;M(<= 10)是垃圾箱候选地点的个数;K(<= 104)是居民点和垃圾箱候选地点之间的道路的条数;DS是居民点与垃圾箱之间不能超过的最大距离。所有的居民点从1到N编号,所有的垃圾箱候选地点从G1到GM编号。

随后K行,每行按下列格式描述一条道路:
P1 P2 Dist
其中P1和P2是道路两端点的编号,端点可以是居民点,也可以是垃圾箱候选点。Dist是道路的长度,是一个正整数。

输出格式:

首先在第一行输出最佳候选地点的编号。然后在第二行输出该地点到所有居民点的最小距离和平均距离。数字间以空格分隔,保留小数点后1位。如果解不存在,则输出“No Solution”。

输入样例1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
输出样例1:
G1
2.0 3.3
输入样例2:
2 1 2 10
1 G1 9
2 G1 20
输出样例2:
No Solution

题目大意:从m个垃圾站里面选取1个站点,让他离居民区的最近的人最远,并且没有超出服务范围ds之内。如果有很多个最远的垃圾站,输出距离所有居民区距离平均值最小的那个。如果平均值还是一样,就输出按照顺序排列垃圾站编号最小的那个、
分析:
因为垃圾站之间也是彼此有路连接的,所以最短路径计算的时候也要把垃圾站算上。所以我们就是堆n+m个点进行Dijkstra计算最短路径。要求计算出1~m号垃圾站距离其他站点的最短路径。这时候可以遍历dis数组,如果dis存在一个距离大于服务范围ds的距离,那么我们就舍弃这个垃圾站。取最最短的路径,这就是距离它最近的垃圾站mindis。如果mindis > ansdis,就是说找到了一个距离居民最小距离的垃圾站是更远的,那就选这个垃圾站,更新ansid为它的id。最后输出
对于垃圾站的字符串编号的处理:如果最近居民区最大的值没有变化但是找到了一个更小的平均距离,那就选这个。我们可以根据输入的是G还是数字,如果是数字就令编号为他自己,如果是G开头的,编号设为n+G后面的数字。

 

1072. Gas Station (30)-PAT甲级真题(Dijkstra)

A gas station has to be built at such a location that the minimum distance between the station and any of the residential housing is as far away as possible. However it must guarantee that all the houses are in its service range.

Now given the map of the city and several candidate locations for the gas station, you are supposed to give the best recommendation. If there are more than one solution, output the one with the smallest average distance to all the houses. If such a solution is still not unique, output the one with the smallest index number.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive integers: N (<= 103), the total number of houses; M (<= 10), the total number of the candidate locations for the gas stations; K (<= 104), the number of roads connecting the houses and the gas stations; and DS, the maximum service range of the gas station. It is hence assumed that all the houses are numbered from 1 to N, and all the candidate locations are numbered from G1 to GM.

Then K lines follow, each describes a road in the format
P1 P2 Dist
where P1 and P2 are the two ends of a road which can be either house numbers or gas station numbers, and Dist is the integer length of the road.

Output Specification:

For each test case, print in the first line the index number of the best location. In the next line, print the minimum and the average distances between the solution and all the houses. The numbers in a line must be separated by a space and be accurate up to 1 decimal place. If the solution does not exist, simply output “No Solution”.

Sample Input 1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
Sample Output 1:
G1
2.0 3.3
Sample Input 2:
2 1 2 10
1 G1 9
2 G1 20
Sample Output 2:
No Solution

题目大意:从m个加油站里面选取1个站点,让他离居民区的最近的人最远,并且没有超出服务范围ds之内。如果有很多个最远的加油站,输出距离所有居民区距离平均值最小的那个。如果平均值还是一样,就输出按照顺序排列加油站编号最小的那个
分析:
因为加油站之间也是彼此有路连接的,所以最短路径计算的时候也要把加油站算上。所以我们就是对n+m个点进行Dijkstra计算最短路径。要求计算出1~m号加油站距离其他站点的最短路径。这时候可以遍历dis数组,如果dis存在一个距离大于服务范围ds的距离,那么我们就舍弃这个加油站。取最最短的路径,这就是距离它最近的加油站mindis。如果mindis > ansdis,就是说找到了一个距离居民最小距离的加油站是更远的,那就选这个加油站,更新ansid为它的id。最后输出
对于加油站的字符串编号的处理:如果最近居民区最大的值没有变化但是找到了一个更小的平均距离,那就选这个。我们可以根据输入的是G还是数字,如果是数字就令编号为他自己,如果是G开头的,编号设为n+G后面的数字。
Update:Github用户littlesevenmo在issue中提出需要添加输入判断,题目中并没有说明两点之间最多只有一条路。也就是说,有可能两点之间有多条路,因此需要添加判断,只存储距离最短的路。另外,也有可能会出现 G1 G1 9999这样的测试数据,因此,自身与自身之间的距离要初始化为0。完善后的代码如下:

1030. Travel Plan (30)-PAT甲级真题(Dijkstra + DFS,输出路径,边权)

A traveler’s map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (<=500) is the number of cities (and hence the cities are numbered from 0 to N-1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

City1 City2 Distance Cost

where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Sample Output
0 2 3 3 40
题目大意:求起点到终点的最短路径最短距离和花费,要求首先路径最短,其次花费最少,要输出完整路径
分析:Dijksta + DFS。 Dijkstra记录路径pre数组,然后用dfs求最短的一条mincost以及它的路径path,最后输出path数组和mincost
注意路径path因为是从末端一直压入push_back到path里面的,所以要输出路径的时候倒着输出

 

L2-013. 红色警报-PAT团体程序设计天梯赛GPLT(图的连通分量个数统计)

战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。

输入格式:

输入在第一行给出两个整数N(0 < N <=500)和M(<=5000),分别为城市个数(于是默认城市从0到N-1编号)和连接两城市的通路条数。随后M行,每行给出一条通路所连接的两个城市的编号,其间以1个空格分隔。在城市信息之后给出被攻占的信息,即一个正整数K和随后的K个被攻占的城市的编号。

注意:输入保证给出的被攻占的城市编号都是合法的且无重复,但并不保证给出的通路没有重复。

输出格式:

对每个被攻占的城市,如果它会改变整个国家的连通性,则输出“Red Alert: City k is lost!”,其中k是该城市的编号;否则只输出“City k is lost.”即可。如果该国失去了最后一个城市,则增加一行输出“Game Over.”。

输入样例:
5 4
0 1
1 3
3 0
0 4
5
1 2 0 4 3
输出样例:
City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.
分析:用图的深度优先遍历判断一个图内的连通分量有多少个,标记为cnt,之后对于每一个输入数据,因为城市a被攻占,所以把a的所有路径标注为不可达(0),再统计连通分量的个数tempcnt,如果tempcnt > cnt + 1,也就是说当现在的连通分量多余以前的连通分量+1的时候,说明改变了图的连通性;(因为城市被攻占本身它城市自己就变成了一个单独的城市,多出来一个连通分量,只要tempcint <= cnt + 1都说明没有改变图的连通性),每一次tempcnt在用完之后把cnt的值更新为tempcnt,保证下一次的判断是建立再已经失去之前这么多城市的基础之上的。
因为题目中说输入保证给出的被攻占的城市编号都是合法的且无重复,所以如果城市失去了n个,就是当前输入的是从0开始的第n-1个数据的时候,就说明Game Over了,最后当if(i == n – 1) printf(“Game Over.\n”);

 

L2-001. 紧急救援-PAT团体程序设计天梯赛GPLT(Dijkstra算法)

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出格式:

第一行输出不同的最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出首尾不能有多余空格。

输入样例:
4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2
输出样例:
2 60
0 1 3
分析:用一遍dijkstra算法。设立num[i]和w[i]表示从出发点到i结点拥有的路的条数,以及能够找到的救援队的数目~~当判定dis[u] + e[u][v] < dis[v]的时候,不仅仅要更新dis[v],还要更新num[v] = num[u], w[v] = weight[v] + w[u]; 如果dis[u] + e[u][v] == dis[v],还要更新num[v] += num[u],而且判断一下是否权重w[v]更小,如果更小了就更新w[v] = weight[v] + w[u];
再设立一个pre[i]表示最短路径的前一个结点,在dis[u] + e[u][v] <= dis[v]的时候更新pre[v] = u,最后递归打印路径即可