观光铁路
一、任务
跳蚤国正在大力发展旅游业,每个城市都被打造成了旅游景点。
许多跳蚤想去其他城市旅游,但是由于跳得比较慢,它们的愿望难以实现。这时,小C听说有一种叫做火车的交通工具,在铁路上跑得很快,便抓住了商机,创立了一家铁路公司,向跳蚤国王请示在每两个城市之间都修建铁路。
然而,由于小C不会扳道岔,火车到一个城市以后只能保证不原路返回,而会随机等概率地驶向与这个城市有铁路连接的另外一个城市。
跳蚤国王向广大居民征求意见,结果跳蚤们不太满意,因为这样修建铁路以后有可能只游览了3个城市(含出发的城市)以后就回来了,它们希望能多游览几个城市。于是跳蚤国王要求小C提供一个方案,使得每只跳蚤坐上火车后能多游览几个城市才回来。
小C提供了一种方案给跳蚤国王。跳蚤国王想知道这个方案中每个城市的居民旅游的期望时间(设火车经过每段铁路的时间都为1),请你来帮跳蚤国王。
【输入格式】
输入的第一行包含两个正整数n、m,其中n表示城市的数量,m表示方案中的铁路条数。
接下来m行,每行包含两个正整数u、v,表示方案中城市u和城市v之间有一条铁路。
保证方案中无重边无自环,每两个城市之间都能经过铁路直接或间接到达,且火车由任意一条铁路到任意一个城市以后一定有路可走。
【输出格式】
输出n行,第i行包含一个实数ti,表示方案中城市i的居民旅游的期望时间。你应当输出足够多的小数位数,以保证输出的值和真实值之间的绝对或相对误差不超过1e-9。
二、要求
对于10%的测试点,n <= 10;
对于20%的测试点,n <= 12;
对于50%的测试点,n <= 16;
对于70%的测试点,n <= 19;
对于100%的测试点,4 <= k <= n <= 21,1 <= u, v <= n。数据有梯度。
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 2000ms
摘要:
本算法与程序课程设计通过图论的方法解决了一个实际问题——计算铁路网络中每个城市居民旅游的期望时间。首先,我们根据城市的铁路连接构建了一个有向图模型,并计算了每个城市的出度,这表示了从一个城市出发到其他城市的直接路径数量。通过分析火车运行的规则——即到达一个城市后随机等概率地向任一相连的城市移动且不返回原路。我们为每个城市建立了一个线性方程,表达了基于相邻城市的期望时间计算当前城市的期望时间的关系。这些方程共同形成了一个线性方程组,其解即为各城市居民旅游的期望时间。最终,我们以高精度格式输出了每个城市的期望旅游时间,确保结果的高准确性。此设计不仅展示了复杂系统建模的能力,也体现了算法在解决现实世界问题中的应用价值。
关键字:图论;系统建模;铁路网络;期望旅游时间
三、系统方案
1、任务要求及算法分析
任务要求:
- 图构建:根据提供的城市连接数据,构建一个有向图,以模拟铁路网络。每个节点代表一个城市,每个有向边代表两个城市间的铁路连接。
- 出度计算:对于图中的每个节点,计算其出度,即从该节点出发的边的数量。这表示从一个城市可以直达的其他城市的数量。
- 方程建立:根据火车运行规则,为网络中的每个城市建立一个方程,表达该城市的平均旅游时间与其邻居城市平均旅游时间的关系。确保考虑火车不会沿原路返回的条件。
- 求解方程组:使用适当的数学方法,求解由所有城市方程构成的线性方程组。确保计算结果满足精度要求。
- 结果输出:将每个城市的期望旅游时间以指定的格式输出。
解题思路:
对于出发点城市1来说,出发到每个子节点的概率之和(出度)与父节点到本节点的概率之和
(入度)相等,且为1。也就是说,乘客一定会回到起点。
对于概率p1 , p2 … … pn 与相对应的值x1 , x2 … … xn
它们的平均期望应该是
这个平均期望对应的概率是
对于某个节点K
到达K的平均期望就是
到达K的概率就是p
算法分析:
时间复杂度: 主要的时间消耗主要体现在两个循环结构的执行上:第一个循环结构用于读取输入数据,并统计每个节点的度数。这个循环结构的时间复杂度为O(m),因为需要遍历所有的边。第二个循环结构用于计算每个节点的平均度数,并输出结果。这个循环结构的时间复杂度为O(n),因为需要遍历所有的节点。时间复杂度为O(m+n)。
空间复杂度: 空间复杂度是O(n),其中n表示节点数。因为代码中使用了一个长度为MAX的数组num来存储每个节点的度数,而节点数最多为n。
数值稳定性: 在计算过程中需注意数值的稳定性和精度问题。
2、方案比较与选择
- 方案一:使用SPFA算法
- 优点:时间复杂度较低,适用于大规模图的处理。
- 缺点:不能保证得到全局最优解,可能产生冗余操作。
- 方案二:使用Dijkstra算法
- 优点:能够保证得到全局最优解,适用于无负权边的图。
- 缺点:时间复杂度较高,不适用于大规模图的处理。
- 方案三:通过输入输出案例找规律
- 优点:代码简短,易于理解。
- 缺点:不清楚通过规律算时间期望的原因。
Dijkstra 算法与 SPFA算法比较
1、负权边处理
代码实现:
#include <iostream>
#include <vector>
#include <queue>
#include <iomanip>
using namespace std;
const int INF = 1e9;
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> edges(m, vector<int>(2));
vector<vector<int>> dist(n, vector<int>(n, INF));
for (int i = 0; i < m; ++i) {
cin >> edges[i][0] >> edges[i][1];
dist[edges[i][0] - 1][edges[i][1] - 1] = 1;
dist[edges[i][1] - 1][edges[i][0] - 1] = 1;
}
vector<int> in_degree(n, 0);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (dist[i][j] != INF) {
in_degree[j]++;
}
}
}
queue<int> q;
for (int i = 0; i < n; ++i) {
if (in_degree[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = 0; v < n; ++v) {
if (dist[u][v] != INF) {
dist[u][v] = min(dist[u][v], dist[u][u] + dist[u][v]);
in_degree[v]--;
if (in_degree[v] == 0) {
q.push(v);
}
}
}
}
for (int i = 0; i < n; ++i) {
double sum = 0;
for (int j = 0; j < n; ++j) {
if (dist[i][j] != INF) {
sum += dist[i][j];
}
}
cout << fixed << setprecision(10) << sum / (n - 1) << endl;
}
return 0;
}
发现规律:
四、算法实现
1、算法流程设计
- 初始化一个长度为MAX的整型数组num,用于存储每个节点的度数。
- 从标准输入读取两个整数n和m,分别表示节点的数量和边的数量。
- 使用一个for循环,循环m次,每次循环中: a. 从标准输入读取两个整数u和v,表示一条边连接的两个节点。 b. 将num[u]和num[v]的值加1,表示这两个节点的度数都增加了1。
- 使用另一个for循环,循环n次,每次循环中: a. 计算当前节点的度数概率p,公式为:p = m * 2.0 / num[i]。 b. 使用printf函数,以保留12位小数的格式输出p。
- 返回0,表示程序正常结束。
2、算法模型构建
根据提供的城市连接数据,构建一个有向图,以模拟铁路网络。每个节点代表一个城市,每个有向边代表两个城市间的铁路连接。使用图论中的最短路径算法来计算从任一城市出发到达其他城市的最短路径长度。
完整代码:
#include<iostream>
using namespace std;
const int MAX = 100;
int num[MAX];
int main()
{
int n, m,i;
cin >> n >> m;
for (i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
num[u]++;
num[v]++;
}
for (i = 1; i <= n; i++)
{
double p = m * 2.0 / num[i];
printf("%.12f\n", p);
}
return 0;
}
时间复杂度: 主要的时间消耗主要体现在两个循环结构的执行上:第一个循环结构用于读取输入数据,并统计每个节点的度数。这个循环结构的时间复杂度为O(m),因为需要遍历所有的边。第二个循环结构用于计算每个节点的平均度数,并输出结果。这个循环结构的时间复杂度为O(n),因为需要遍历所有的节点。
时间复杂度:O(m+n)。
空间复杂度:O(n),其中n表示节点数。
五、工程管理及经济学分析
1、算法实现所涉及的工程管理
-
项目管理
- 项目规划:制定算法实现铁路建设计划,包括城市间铁路的数量、长度和连接方式。
-
团队协作
- 沟通协调:建立有效的沟通机制,确保团队成员之间的信息流通。
- 任务分配:根据团队成员的能力和特长,合理分配任务,提高工作效率。
- 冲突解决:及时解决团队内部的矛盾和冲突,维护良好的团队氛围。
-
进度管理
- 进度计划:制定详细的进度计划,确保项目按时完成。
- 进度跟踪:实时跟踪工程进度,及时发现并解决影响进度的问题。
- 进度调整:根据实际情况,适时调整工程进度计划,确保项目顺利进行。
注意事项:
- 数据准确性:输入数据的准确性至关重要,任何错误都可能导致算法结果的偏差。
- 算法效率:考虑到大规模的城市数量,算法的效率必须足够高。
- 结果精确度:输出的结果应保证足够的小数位数,以满足误差不超过1e-9的要求。
2、算法实现中体现的经济学分析
- 成本效益分析:在规划铁路网络时,需要对比建设和维护铁路的成本与通过提升旅游效率带来的收益。包括直接收益(如票价收入)和间接收益(如增加的就业机会、促进当地经济发展等)。
- 需求预测:对旅游需求进行预测,了解不同城市间的旅客流量,以及旅游高峰期和淡季的变化。有助于设计出能够满足不同时间段需求的铁路服务。
- 外部性:考虑铁路建设和运营可能带来的正面或负面外部效应,例如减少交通拥堵、环境污染,或者提高地区间的经济联系。
六、总结
1、过程难点及反思
1. 理解问题需求
2. 选择合适的数据结构和算法
3. 编码实现
2、心得与体会
1. 理解问题的复杂性
2. 数据结构与算法的选择
3. 编码实现的挑战