题目链接
https://pintia.cn/problem-sets/994805342720868352/problems/1038430013544464384
题解
题目要求
- 现在给你一些环,请你找到其中与旅行商问题答案最接近的那个环(旅行商问题的定义在此不再说明)
- 输入
- N:大于2,不超过200,城市的数量
- M:无向图中边的数量,
- M条边:每条边表示为
City1 City2 Dist
,其中城市索引为[1,N],城市间距离为不超过100的正数 - K:正整数,path的数量
- K条path:每条path的格式为:
n c1 c2 c3 … cn
,其中n是path中城市的数量,ci是城市索引
- 输出
- 对于每条path,输出
Path X: TotalDist (Description)
,其中X是[1,K],TotalDist是总距离(不存在则输出NA),Description是- 经过每个城市的简单环:
TS simple cycle
- 经过每个城市的环,但不是简单环:
TS cycle
- 不是经过每个城市的环:
Not a TS cycle
- 经过每个城市的简单环:
- 最终输出
Shortest Dist(X) = TotalDist
,其中X是和旅行商问题解最接近的那个环的索引,TotalDist是其距离总和。(已确保只有一个解)
- 对于每条path,输出
解题思路
-
距离用二维数组表示,默认值为0,为0则说明两个城市间不存在边
-
读取每条path时,用一维数组存储某个节点被访问的次数(注意城市索引是1到N)
在路径合法的前提下
- TS cycle:即经过每个城市并且是一个环,即每个城市被访问的次数都大于0且首尾城市相同
- TS simple cycle:在TS cycle的基础上,要求没有子环,只有起点城市被访问过2次,其它城市都只被访问过一次
-
将k个path的结果存放在一维数组中
代码
// Problem: PAT Advanced 1150
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/1038430013544464384
// Tags: Graph TSP
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int distances[205][205]; // 各个城市之间的距离。如果为0,则说明两个城市间无边、不可直达
int main()
{
int n, m, k;
scanf("%d %d", &n, &m);
int c1, c2, dist;
for (int i = 0; i < m; i++){ // 存储各个城市之间的距离
scanf("%d %d %d", &c1, &c2, &dist);
distances[c1][c2] = distances[c2][c1] = dist;
}
int bestX, bestDist = INT_MAX;
scanf("%d", &k);
for(int x = 1; x <= k; x++){
vector<int> visited(n + 1, 0);
int numOfCities, firstCity, pathTotalDist = 0;
bool pathIslegal = true;
scanf("%d %d", &numOfCities, &firstCity);
visited[firstCity] += 1; // 访问第一个城市
c1 = firstCity; // 更新上一个城市
for(int i = 0 ; i < numOfCities - 1; i++){
scanf("%d", &c2); // 读取当前城市
if (distances[c1][c2] != 0){
visited[c2] += 1;
pathTotalDist += distances[c1][c2]; // 计算该路径的总距离
}
else{ // path中两个城市不存在边
pathIslegal = false;
}
c1 = c2; // 更新上一个城市
}
if (!pathIslegal){ // 路径非法
printf("Path %d: NA (Not a TS cycle)
", x);
continue;
}
if (firstCity != c2){ // 在路径合法的前提下,第一个城市和最后一个城市不同,则该路径不是环
printf("Path %d: %d (Not a TS cycle)
", x, pathTotalDist);
continue;
}
bool isTS = true;
for (int i = 1; i < n + 1; i++){
if (visited[i] < 1){
isTS = false;
break;
}
}
if (!isTS){ // 该路径没有经过所有城市
printf("Path %d: %d (Not a TS cycle)
", x, pathTotalDist);
continue;
}
bool isSimple = true;
for (int i = 1; i < n + 1; i++){ // 已确保是环且经过所有城市,判断是否是简单环,并更新最短TS环路
if (pathTotalDist < bestDist){
bestX = x;
bestDist = pathTotalDist;
}
if (i != firstCity && visited[i] > 1){
isSimple = false;
}
}
if (isSimple)
printf("Path %d: %d (TS simple cycle)
", x, pathTotalDist);
else
printf("Path %d: %d (TS cycle)
", x, pathTotalDist);
}
printf("Shortest Dist(%d) = %d
", bestX, bestDist);
return 0;
}
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!