版权声明:如若转载,请联系作者。 https://blog.csdn.net/liu16659/article/details/86769237
PAT 1150
C++
版
1.题意
给出一个无向图的顶点,边信息。然后给出一系列的访问序列,判断这些序列属于哪种序列。然后给出最短的路径信息。
路径类型有:
- 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.
2.分析
题很简单,但是做起来很麻烦。
- 使用二维数组存储 边信息
- 使用一维数组存储节点是否访问信息
- 使用一维数组存储遍历的节点信息
- 使用map存储最后的结果信息,找出最短路径
3.代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#define maxn 20005
using namespace std;
int main(){
int isVisit[maxn];
int edge[205][205];
int N,M;//N 是城市数; M是边数
cin >> N >> M;
int i ,j;
int ver1,ver2,a;
for(i = 0;i< 205;i++){
for(j = 0;j< 205;j++)
edge[i][j] = -1;
}
for(i = 0;i< M ;i++){
cin >> ver1>> ver2 >> a;
edge[ver1][ver2] = a;
edge[ver2][ver1] = a;
}
map<int,int> res;//保存最后的筛选结果
int queryNum;
cin >> queryNum;
for(i = 0;i< queryNum;i++){
int num;//表示当前访问城市的个数
int array[maxn];//用于存储查询的序列
cin >> num;
int dis = 0;//节点之间的总距离
int pre;//表示上一个节点
int flag = 0;
memset(isVisit,0,sizeof(isVisit));//初始化所有的城市节点访问信息
for(j = 0;j< num;j++){
cin >> array[j];
isVisit[array[j]] = 1;//说明这个节点访问到了
if(j!=0){//如果当前的节点不是0
if(edge[pre][array[j]] != -1){
dis += edge[pre][array[j]];//求出总和
}
else{//说明两个城市不存在线路
flag = 2;
}
}
pre = array[j];
}
if(flag == 2){
cout << "Path " << i+1 <<": NA (Not a TS cycle)"<<"\n";
continue;
}
for(j = 1;j <= N;j++ ){
if(isVisit[j] == 0){
flag = 1;//表示城市访问不全
break;
}
}
if(j <= N || (array[0] != array[num-1])){//说明不是 cycle
cout << "Path " << i+1 <<": "<<dis<<" (Not a TS cycle)"<<"\n";
}
else{
if(num == N + 1){//说明是一个 TS simple cycle
cout << "Path " << i+1 <<": "<<dis<<" (TS simple cycle)"<<"\n";
}
else{//说明有重复访问城市
cout << "Path " << i+1 <<": "<< dis <<" (TS cycle)"<<"\n";
}
res[i+1]= dis;
}
}
int minDis = 999999;//不一定是最大值
int minIndex;
for(map<int,int>::iterator it = res.begin();it!=res.end();it++){
if(minDis > it->second ){
minDis = it->second;
minIndex = it->first;
}
}
cout << "Shortest Dist("<<minIndex << ") = "<<minDis<<"\n";
}
4.测试用例
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
7 6 3 2 5 4 1 6
9 6 2 1 6 3 4 5 2 6
4 1 2 5 1
7 6 1 2 5 4 3 1
5.执行结果
一遍AC。
6.坑点
6.1 错误的地方break
为了让代码更加简洁,我本想在flag=2之后添加break
。但是后来却发现了错误。
if(j!=0){//如果当前的节点不是0
if(edge[pre][array[j]] != -1){
dis += edge[pre][array[j]];//求出总和
}
else{//说明两个城市不存在线路
flag = 2;
//break;记住这里不能break,否则会造成错误答案
}
}
这里错误的原因是:那一行的输入还没有结束,结果你却结束了。导致输入数据出错,从而导致执行结果出错。【因为这里的输入和处理是在同一个for循环中处理的】