1. 程式人生 > 其它 >1150 Travelling Salesman Problem (25 分)(圖論)

1150 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:

n C1 C2 ……Cn

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

題目大意:

給出一條路徑,判斷這條路徑是這個圖的旅行商環路、簡單旅行商環路還是非旅行商環路~

分析:

如果給出的路徑存在某兩個連續的點不可達或者第一個結點和最後一個結點不同或者這個路徑沒有訪問過圖中所有的點,那麼它就不是一個旅行商環路(flag = 0)~如果滿足了旅行商環路的條件,那麼再判斷這個旅行商環路是否是簡單旅行商環路,即是否訪問過n+1個結點(源點訪問兩次)~最後輸出這些旅行商環路中經過的路徑最短的路徑編號和路徑長度~

原文連結:https://blog.csdn.net/liuchuo/article/details/82560843

我的題解

感覺自己寫的這堆shit邏輯很不清晰,本來拿了21分已經很不錯了
結果發現minsum寫的太小了,改了改驚奇地發現竟然AC了!震驚!!

#include <bits/stdc++.h>

using namespace std;
int n,m;
int e[210][210];
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif
    int a,b,dist;
    cin>>n>>m;
    for(int i=0; i<m; i++)
    {
        cin>>a>>b>>dist;
        e[a][b]=e[b][a]=dist;
    }
    int k,num,id,minsum=999999;
    cin>>k;
    for(int query=1; query<=k; query++)
    {
        cin>>num;
        vector<int> v(num);
        set<int> s;
        int flag1=1,flag2=1,flag3=1;
        for(int i=0; i<num; i++)
        {
            cin>>v[i];
            s.insert(v[i]);
        }
        if(s.size()!=n||v[0]!=v[num-1])
            flag1=0;
        if(flag1)
        {
            if(num-1==n)
                flag2=0;
        }
        int sum=0;
        for(int i=0; i<num-1; i++)
        {
            if(e[v[i]][v[i+1]]==0)
            {
                flag3=0;
                flag1=0;
                flag2=0;
                break;
            }
            int dis=e[v[i]][v[i+1]];
            sum+=dis;
        }
        if(flag1&&!flag2)
        {
            if(sum<minsum)
            {
                id=query;
                minsum=sum;
            }
            printf("Path %d: %d (TS simple cycle)\n",query,sum);
        }
        else if(flag1&&flag2)
        {
            if(sum<minsum)
            {
                id=query;
                minsum=sum;
            }
            printf("Path %d: %d (TS cycle)\n",query,sum);
        }
        else if(!flag1&&flag3)
        {
            printf("Path %d: %d (Not a TS cycle)\n",query,sum);
        }
        else if(flag3==0)
        {
            printf("Path %d: NA (Not a TS cycle)\n",query);
        }
    }
    printf("Shortest Dist(%d) = %d",id,minsum);
    return 0;
}

柳神題解

還是學習一下大佬的題解吧Orz
重新理解了一下if...else if...else

隱藏的條件判斷是:
條件2,預設條件1不成立;
條件3,預設條件1和條件2不成立;
...

#include <iostream>
#include <vector>
#include <set>
using namespace std;
int e[300][300], n, m, k, ans = 99999999, ansid;
vector<int> v;
void check(int index) {
    int sum = 0, cnt, flag = 1;
    scanf("%d", &cnt);
    set<int> s;
    vector<int> v(cnt);
    for (int i = 0; i < cnt; i++) {
        scanf("%d", &v[i]);
        s.insert(v[i]);
    }
    for (int i = 0; i < cnt - 1; i++) {
        if(e[v[i]][v[i+1]] == 0) flag = 0;
        sum += e[v[i]][v[i+1]];
    }
    if (flag == 0) {
        printf("Path %d: NA (Not a TS cycle)\n", index);
    } else if(v[0] != v[cnt-1] || s.size() != n) {
        printf("Path %d: %d (Not a TS cycle)\n", index, sum);
    } else if(cnt != n + 1) {
        printf("Path %d: %d (TS cycle)\n", index, sum);
        if (sum < ans) {
            ans = sum;
            ansid = index;
        }
    } else {
        printf("Path %d: %d (TS simple cycle)\n", index, sum);
        if (sum < ans) {
            ans = sum;
            ansid = index;
        }
    }
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++) {
        int t1, t2, t;
        scanf("%d%d%d", &t1, &t2, &t);
        e[t1][t2] = e[t2][t1] = t;
    }
    scanf("%d", &k);
    for (int i = 1; i <= k; i++) check(i);
    printf("Shortest Dist(%d) = %d\n", ansid, ans);
    return 0;
}

本文來自部落格園,作者:勇往直前的力量,轉載請註明原文連結:https://www.cnblogs.com/moonlight1999/p/15942722.html