18秋第三题 PAT甲级 1150 Travelling Salesman Problem (25分) 简单图论

本文介绍了PAT甲级编程竞赛中的1150题——旅行商问题的变种。通过分析输入规格、输出规格以及样例,文章详细讲解了如何判断给定的路径是否构成旅行商问题的解决方案,并提供了相应的无向图和回路判断逻辑。最后,给出了满足题目要求的满分代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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:

n C​1​​ C​2​​ ... C​n​​

where n is the number of cities in the list, and C​i​​'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

名词解释

1.undirected graph
无向图,就是A和B点有连线的话,是双向的
在代码层面就是int G[maxn][maxn],存边的时候G[a][b]=G[b][a]=cost

2.cycle
回路,就是说图的顶点序列中,第一个顶点和最后一个顶点相同

3.simple cycle
简单回路,就是图的顶点序列中,除了第一个顶点和最后一个顶点相同外,其余顶点不重复出现的回路

题目大意

给出无向图和顶点序列,判断是不是旅行商回路和简单回路。

分析

这道题的输出要求是这样的:

  • 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.

稍作整理,可以发现这道题的判断逻辑基本上照搬输出的要求:
1.Not a TS cycle:顶点序列首尾不同 或者 没有遍历每个城市
2.TS cycle:遍历了每个城市但是顶点序列有重复
3.TS simple cycle:不用单独判断了,除了前两种情况其余都是

这就是“简单图论”题目的典型,在PAT甲级考试挺常见的图论考法。

满分代码

#include<iostream>
#include<vector>
#include<set>
#include<cctype>
using namespace std;
const int maxn=205;
int n,m,k,u,w,c;
int G[maxn][maxn];
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        scanf("%d %d %d",&u,&w,&c);
        G[u][w]=G[w][u]=c;
    }
    cin>>k;
    int sp=1,sd=9999999;
    for(int i=1;i<=k;i++){
        cin>>u;
        vector<int> v(u+5);
        set<int> s;
        int dis=0,f=0;
        for(int i=1;i<=u;i++){
            scanf("%d",&v[i]);
            s.insert(v[i]);
            if(i!=1){
                dis+=G[v[i-1]][v[i]];
                if(G[v[i-1]][v[i]]==0)f=1;
            }
        }
        printf("Path %d: ",i);
        if(f==1) printf("NA ");
        else printf("%d ",dis);
        if(s.size()!=n || v[1]!=v[u] ||f==1){
            printf("(Not a TS cycle)\n");
            continue;
        }else if(u>n+1){
            printf("(TS cycle)\n");
        }else{
            printf("(TS simple cycle)\n");
            
        }
        if(sd>dis){
            sd=dis;
            sp=i;
        }
    }
    printf("Shortest Dist(%d) = %d\n",sp,sd);
    return 0;
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值