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;
}

猜你喜欢

转载自blog.csdn.net/qq_41317652/article/details/82560886