【题解】【AcWing】1643. 旅行商问题

304 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1643. 旅行商问题

原题传送:AcWing 1643. 旅行商问题

“旅行商问题”是这样一个问题:“给出一个城市列表以及每对城市之间的距离,访问每个城市并返回原城市的最短路线是什么?”

这是组合优化中的一个NP难题,在运筹学和理论计算机科学中十分重要。

在此问题中,请你从给定的路径列表中找到最接近旅行商问题的解的路径。

输入格式

第一行包含两个整数 NNMM ,分别表示城市数量以及无向图中边的数量。

接下来 MM 行,每行以City1 City2 Dist格式描述一条边,其中城市编号从 11NNDist为正且不超过 100100

再一行包含一个整数 KK ,表示给定路径的数量。

接下来 KK 行描述路径,格式为:

nn C1C_1 C2C_2CnC_n

nn 表示给定路径经过的城市的数目, CiC_i 是路径中经过的城市的编号。

输出格式

对于每个路径,在一行中输出Path X: TotalDist (Description)

其中X是路径编号(从 11 开始),TotalDist 表示路径总距离(如果距离不存在,则输出 NA),Description 是下列中的一项:

  • TS simple cycle,如果这是一个访问每个城市的简单回路。
  • TS cycle,如果这是一个访问每个城市的回路,但不是简单回路。
  • Not a TS cycle,如果这不是一个访问了每个城市的回路。

最后一行,输出Shortest Dist(X) = TotalDistX 是最接近旅行商问题解决方案的回路编号,TotalDist 是其总距离。

保证有唯一解。

数据范围

2<N2002<N \le 200 , N1MN(N1)2N-1 \le M \le \frac{N(N-1)}{2}1K10001 \le K \le 1000 , 1n3001 \le n \le 300

输入样例:

6 10
6 2 1
3 4 1
1 5 1
2 5 1
3 1 8
4 1 6
1 6 1
6 3 1
1 2 1
4 5 1
7
7 5 1 4 3 6 2 5
7 6 1 3 4 5 2 6
6 5 1 4 3 6 2
9 6 2 1 6 3 4 5 2 6
4 1 2 5 1
7 6 1 2 5 4 3 1
7 6 3 2 5 4 1 6

输出样例:

Path 1: 11 (TS simple cycle)
Path 2: 13 (TS simple cycle)
Path 3: 10 (Not a TS cycle)
Path 4: 8 (TS cycle)
Path 5: 3 (Not a TS cycle)
Path 6: 13 (Not a TS cycle)
Path 7: NA (Not a TS cycle)
Shortest Dist(4) = 8

思路:

如果访问结点之间有无穷大的边、没有访问所有城市或者起点不等于终点,说明不是一个访问了每个城市的回路,如果输入点数不是点数+1说明不是简单回路,输出回路中总距离最小的路径。

题解:

#include <bits/stdc++.h>

using namespace std;

const int N = 210, INF = 0x3f3f3f3f;

int n, m;
int g[N][N], vers[310];
bool st[N];

int main()
{
	scanf("%d%d", &n, &m);
	
	memset(g, 0x3f, sizeof g);
	for(int i = 0; i < m; i++)
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		g[a][b] = g[b][a] = c;
	}
	
	int k;
	scanf("%d", &k);
	
	int min_dist = INF, min_id;
	for(int T = 1; T <= k; T++)
	{
		int cnt;
		scanf("%d", &cnt);
		for(int i = 0; i < cnt; i++) scanf("%d", &vers[i]);
		
		int sum = 0;
		bool success = true;
		memset(st, 0, sizeof st);
		for(int i = 0; i + 1 < cnt; i++)
		{
			int a = vers[i], b = vers[i + 1];
			if(g[a][b] == INF)
			{
				sum = -1;
				success = false;
				break;
			}
			else sum += g[a][b];
			st[a] = true;
		}
		
		for(int i = 1; i <= n; i++)
		{
			if(!st[i])
			{
				success = false;
				break;
			}
		}
		
		if(vers[0] != vers[cnt - 1]) success = false;
		
		if(sum == -1) printf("Path %d: NA (Not a TS cycle)\n", T);
		else
		{
			if(!success) printf("Path %d: %d (Not a TS cycle)\n", T, sum);
			else
			{
				if(cnt == n + 1) printf("Path %d: %d (TS simple cycle)\n", T, sum);
				else 	printf("Path %d: %d (TS cycle)\n", T, sum);
				
				if(min_dist > sum)
				{
					min_dist = sum;
					min_id = T;
				}
			}
		}
	}
	
	printf("Shortest Dist(%d) = %d\n", min_id, min_dist);
	
	return 0;
}