PAT 甲级 A1150 Travelling Salesman Problem(25 分)

从一开始的不认识单词,到后来的无从下手,再到现在总算能独立解题而不看前辈们的题解了,加油,为我自己也为正在努力的你!

The “travelling salesman problem” asks the following question: “Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city and returns to the origin city?” It is an NP-hard problem in combinatorial optimization, important in operations research and theoretical computer science. (Quoted from “https://en.wikipedia.org/wiki/Travelling_salesman_problem”.)

In this problem, you are supposed to find, from a given list of cycles, the one that is the closest to the solution of a travelling salesman problem.

Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive integers N (2<N≤200), the number of cities, and M, the number of edges in an undirected graph. Then M lines follow, each describes an edge in the format City1 City2 Dist, where the cities are numbered from 1 to N and the distance Dist is positive and is no more than 100. The next line gives a positive integer K which is the number of paths, followed by K lines of paths, each in the format:
在这里插入图片描述
where n is the number of cities in the list, and Ci’s are the cities on a path.

Output Specification:
For each path, print in a line Path X: TotalDist (Description) where X is the index (starting from 1) of that path, TotalDist its total distance (if this distance does not exist, output NA instead), and Description is one of the following:

TS simple cycle if it is a simple cycle that visits every city;
TS cycle if it is a cycle that visits every city, but not a simple cycle;
Not a TS cycle if it is NOT a cycle that visits every city.
Finally print in a line Shortest Dist(X) = TotalDist where X is the index of the cycle that is the closest to the solution of a travelling salesman problem, and TotalDist is its total distance. It is guaranteed that such a solution is unique.

Sample Input:
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

Sample Output:
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

下面直接给出代码,必要之处会给出注释【图论】

#include<iostream>
#include<map>
#include<vector>
using namespace std;
map< int,bool > city;	//判断两个city是否有路径
map< int,vector<int> > dist;	//记录两个city之间的distance
int ans[2] = {0,20010};		//更新the shortest path
int main(){
	int n,m,k,x;
	cin >> n >> m;
	for(int i = 1;i <= m;i++){
		int tp1,tp2,tp3;
		cin >> tp1 >> tp2 >> tp3;
		dist[tp1*1000+tp2].push_back(tp3);		//city1->city2的distance
		dist[tp2*1000+tp1].push_back(tp3);		//city2->city1的distance
		city[tp1*1000+tp2] = city[tp2*1000+tp1] = true;		//用以判断city1和city2之间是否有路径
	}
	cin >> k;
	for(int i = 1;i <= k;i++){
		cin >> x;
		vector<int> path(x);
		int visit[n+1] = {0};
		int judge = 0,totaldist = 0;
		for(int j = 0;j < x;j++) cin >> path[j];
		for(int j = 1;j < x;j++){
			if(city[path[j]*1000+path[j-1]] == false){		//city1和city2没有路径,break
				printf("Path %d: NA (Not a TS cycle)\n",i);
				judge = 2;
				break;
			}
			totaldist += dist[path[j]*1000+path[j-1]][0];	//记录distance
			visit[path[j]] = 1;		//用以判断是否访问过每个city
		}
		for(int j = 1;j <= n;j++)
			if((visit[j] == 0 && judge != 2) || (path[0] != path[x-1] && judge != 2)) judge = 1;		//找出非cycle path
		if(totaldist < ans[1] && judge == 0){	//更新the shortest distance
			ans[0] = i;
			ans[1] = totaldist;
		}
		if(judge == 1)
			printf("Path %d: %d (Not a TS cycle)\n",i,totaldist);
		else if(judge == 0 && x == n+1)
			printf("Path %d: %d (TS simple cycle)\n",i,totaldist);
		else if(judge == 0 && x > n+1)
			printf("Path %d: %d (TS cycle)\n",i,totaldist);
	}
	printf("Shortest Dist(%d) = %d",ans[0],ans[1]);		输出the shortest distance
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值