1 条题解
-
0
说明
本题要求计算邮递员遍历所有街道至少一次并返回起点的最小费用。关键在于利用欧拉路径和弗洛伊德算法处理奇数度节点,确保路径最短。
算法标签
- 图论:处理街道和交叉口的图结构
- 欧拉路径:判断是否存在欧拉回路或路径
- 弗洛伊德算法:计算所有交叉口之间的最短路径
- 贪心算法:选择最优路径组合
解题思路
-
问题分析:
- 邮递员需要遍历所有街道至少一次并返回起点。
- 街道的费用由名称长度决定。
- 最多有两个奇数度交叉口,其他均为偶数度。
-
关键步骤:
- 统计每个交叉口的度数。
- 计算所有街道的总长度。
- 若存在两个奇数度交叉口,计算它们之间的最短路径并加到总长度中。
- 若所有交叉口均为偶数度,直接输出总长度。
-
算法选择:
- 使用弗洛伊德算法预处理所有交叉口之间的最短路径。
- 根据欧拉路径的性质决定是否需要额外路径。
分析
-
输入处理:
- 读取街道名称,统计交叉口度数和街道长度。
- 构建邻接矩阵,记录交叉口之间的距离。
-
弗洛伊德算法:
- 计算所有交叉口之间的最短路径,存储在邻接矩阵中。
-
欧拉路径判断:
- 统计奇数度交叉口数量。
- 若有两个奇数度交叉口,找到它们之间的最短路径并累加。
-
结果输出:
- 输出最小旅行费用。
实现步骤
-
初始化:
- 邻接矩阵初始化为无穷大。
- 度数数组初始化为0。
-
处理输入:
- 读取街道名称,更新邻接矩阵和度数数组。
- 累加所有街道长度到总费用。
-
弗洛伊德算法:
- 三重循环更新最短路径。
-
处理奇数度节点:
- 若存在两个奇数度节点,找到它们之间的最短路径并累加。
-
输出结果:
- 根据处理结果输出最小费用。
代码解释
- 邻接矩阵初始化:
g
数组初始化为INF
,表示初始时交叉口之间无直接连接。 - 度数统计:
degree
数组记录每个交叉口的度数。 - 弗洛伊德算法:
floyd
函数计算所有交叉口之间的最短路径。 - 奇数度处理:找到两个奇数度交叉口,累加它们之间的最短路径到总费用。
- 结果输出:根据是否存在奇数度交叉口输出相应的最小费用。
该方法通过图论算法高效地解决了邮递员问题,确保在合理时间内计算出最小旅行费用。
代码
/* UVA117 POJ1237 The Postal Worker Rings Once */ #include <iostream> #include <string> #include <cstdio> #include <cstring> using namespace std; /* Floyd-Warshall算法:计算图中任意2点之间的最短距离 * 复杂度:O(N×N×N) * 输入:n 全局变量,图结点数 * g 全局变量,邻接矩阵,g[i][j]表示结点i到j间的边距离 * 输出:g 全局变量 */ const int INF = 0x3f3f3f3f; const int N = 26; int g[N][N]; void floyd() { for(int k = 0; k < N; k++) for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) g[i][j] = min(g[i][j], g[i][k] + g[k][j]); } int degree[N]; int main() { std::ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); string s; int ans = 0; memset(g, INF, sizeof(g)); memset(degree, 0, sizeof(degree)); while(cin >> s) { if(s == "deadend") { int u = -1, v = -1; for(int i = 0; i < N; i++) if(degree[i] & 1) { if(u == -1) u = i; else v = i; } floyd(); if(u != -1) printf("%d\n", ans + g[u][v]); else printf("%d\n", ans); memset(g, INF, sizeof(g)); memset(degree, 0, sizeof(degree)); ans = 0; } else { g[s[s.size() - 1] - 'a'][s[0] - 'a'] = g[s[0] - 'a'][s[s.size() - 1] - 'a'] = s.size(); degree[s[s.size() - 1] - 'a']++; degree[s[0] - 'a']++; ans += s.size(); } } return 0; }
- 1
信息
- ID
- 238
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者