1150 Travelling Salesman Problem

1150 Travelling Salesman Problem(25 point(s))

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

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

//AC code 
/*
  1:输入数据,用邻接矩阵存储边
  2:读入一条待测路v[i],并插入 set<int> s;
  3: 遍历待测路径,sum 统计有效路径长度,并用 flag 标记是否有路径不可达,若不可达,及时跳出 
  4:ok,现在开始枚举可能出现结果:
     (1):: falg== 0 ,即路径不合法 
     (2):: flag== 1 ,存在路径首位不同(有去无回 ) 或者 路径中规定景点没逛到(偷工减料) 
     (3):: 到此步,说明逛了一圈且规定景点都逛了,满足旅行商环路的条件,路径合法 
           再判断是否走了n+1各节点(是否存在一个景点光了两次)
  5: 输出最短合法路径长度 
  6:注意格式输出 
*/
#include<iostream> 
#include<vector>
#include<set>
#include<climits>
using namespace std;

int e[300][300],n, m, k, ans = INT_MAX,ans_id;
vector<int> v;

void check(int index){
    int sum=0,cnt;
    cin>>cnt;
    set<int>s;
    vector<int>v(cnt);
    for (int i=0;i<cnt;i++){
        scanf("%d",&v[i]);
        s.insert(v[i]); 
        //插入自动排序,并删除重复元素 
        /*set集合容器实现了红黑树的平衡二叉检索树的数据结构,
         它会自动调整二叉树的排列,把元素放到适当的位置。
         set容器所包含的元素的值是唯一的,集合中的元素按一定的顺序排列。
        用迭代器访问测试 : 
        set<int>::iterator it;
        for(it=s.begin() ;it!=s.end() ;it++)
           cout<<(*it)<<" ";
        */ 
    }
    bool flag=true; // flag 用于标记是否存在不可达路径  
    for (int i=0;i<cnt-1;i++){
        if(e[v[i]][v[i+1]]== 0){
            flag=false; break; // 跳出节省时间 
        }
        sum+=e[v[i]][v[i+1]];
    }
    if(flag==false){ 
        cout<<"Path "<<index<<": NA (Not a TS cycle)"<<endl; 
    }else if(v[0]!=v[cnt-1] || s.size()!= n){ 
        cout<<"Path "<<index<<": "<<sum<<" (Not a TS cycle)"<<endl; 
    }else if(cnt!=n+1){  
        cout<<"Path "<<index<<": "<<sum<<" (TS cycle)"<<endl;
        if (sum<ans){
            ans=sum;
            ans_id=index; 
        }
    } else{ //源点访问两次,simple cycle 
        cout<<"Path "<<index<<": "<<sum<<" (TS simple cycle)"<<endl;
        if (sum<ans){
            ans =sum;
            ans_id=index;
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=0;i<m;i++) {
        int c1,c2,c;
        cin>>c1>>c2>>c;
        e[c1][c2]=e[c2][c1]=c;
    }
    cin>>k;
    for(int i=1;i<=k;i++) check(i);
    cout<<"Shortest Dist("<<ans_id<<") = "<<ans<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZCAIHUI_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值