一、题目描述
Input Specification:
Output Specification:
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
二、解题思路
如果一个序列经过所有结点并且最后一个结点是第一个结点,则构成一个TS cycle,除了第一个结点和最后一个结点,如果经过某个结点两次,那么就不是一个simple cycle,前后结点不相连则应该输出NA。基于这些,代码就不难设计出来了,详情可见代码注释。
三、AC代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 220;
const int INF = 100000;
int G[maxn][maxn]; //邻接矩阵
int main()
{
int N, M, Q, K, tmp, a, b, ansdis = INF, anspath;
scanf("%d%d", &N, &M);
fill(G[0], G[0]+maxn*maxn, INF); //初始化为INF
for(int i=0; i<M; i++) //输入数据
{
scanf("%d%d%d", &a, &b, &tmp);
G[a][b] = G[b][a] = tmp;
}
scanf("%d", &Q);
for(int i=0; i<Q; i++)
{
int tempdis = 0;
int cnt[N+1] = {
0};
bool na = false, ts = true, sim = true; //标志是否应该输出NA,是否为TS cycle,是否simple
vector<int> vertex;
scanf("%d", &K);
vertex.resize(K);
for(int j=0; j<K; j++)
{
scanf("%d", &vertex[j]);
if(j > 0)
{
if(G[vertex[j-1]][vertex[j]] < INF) tempdis += G[vertex[j-1]][vertex[j]]; //如果前后结点是连接的
else
{
na = true; //前后结点不连接则应输出NA
ts = false;
}
}
cnt[vertex[j]]++; //统计每个结点出现的次数
if(j < K-1 && cnt[vertex[j]] > 1) sim = false; //除了最后一个结点和第一个节点是一样的,如果有结点出现了两次则不是simple cycle
}
for(int j=1; j<=N; j++)
if(cnt[j] == 0) ts = false; //如果存在没有遍历到的点
if(vertex[0] == vertex[K-1] && ts && tempdis < ansdis) //更新答案
{
ansdis = tempdis;
anspath = i+1;
}
if(na) //输出
printf("Path %d: NA (Not a TS cycle)\n", i+1);
else if(vertex[0] != vertex[K-1] || !ts)
printf("Path %d: %d (Not a TS cycle)\n", i+1, tempdis);
else
printf("Path %d: %d %s\n", i+1, tempdis, sim ? "(TS simple cycle)" : "(TS cycle)");
}
printf("Shortest Dist(%d) = %d", anspath, ansdis);
return 0;
}