PAT 1122
C++
版
1.题意
给出一个无向图的顶点,边信息。然后输入一串查询数字,问,输入的这些查询数字是否能够组成一个simple cycle
。
- 这里
simple
的定义指的是:不含冗余顶点 -
cycle
的定义就是:给出的顶点集形成了一个环
如果是simple cycle
,则输出YES
;如果不是simple cycle
,则输出NO
;
2.分析
针对题意,我们可以清楚的了解到:如果是一个simple cycle
,必须满足如下几个条件:
- 是否
simple
? - 起点和终点是否相同?
- 是否不涉及到所有的节点 ?
满足上述所有条件之后,再判断相邻的两个顶点是否存在边?
3.代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<set>
#define maxn 2005
//因为maxn是用于做查询输入的,所以其范围可能会比较大,可能会超过200
using namespace std;
int edge[maxn][maxn];//使用邻接矩阵存边的信息
int main(){
int N,M,K;
cin >> N>>M;
int i,j,z;
int ver1,ver2;
set<int> vertex;
for(i = 0;i< M;i++){
cin >> ver1 >> ver2;
edge[ver1][ver2] = 1;//有边
edge[ver2][ver1] = 1;//有边
}
cin >> K;
int verNum;
int query[maxn];
for(i = 0;i< K;i++){
cin >> verNum;
memset(query,0,sizeof(query));//重置为0
vertex.clear();
for(j = 0;j < verNum;j++){
cin >> query[j];
vertex.insert(query[j]);
}
if(verNum != (N+1) || query[0] != query[N] || vertex.size()!=N) {//是否 simple || 如果起点和终点不同,不是cycle ||如果不涉及到所有的节点
cout <<"NO\n";
}
else{//这个时候才进入判断
for(z = 0; z < verNum -1; z++) {
//cout << query[z]<<" ";
if(edge[query[z]][query[z+1]] != 1){
cout <<"NO\n";
break;
}
}
if(z == verNum - 1){
cout <<"YES\n";
}
}
}
}
4.测试用例
6 10
6 2
3 4
1 5
2 5
3 1
4 1
1 6
6 3
1 2
4 5
6
7 5 1 4 3 6 2 5
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 3 4 5 2 6
7 6 1 2 5 4 3 1
6 10
6 2
3 4
1 5
2 5
3 1
4 1
1 6
6 3
1 2
4 5
1
7 1 2 5 1 2 5 1
5.总结
在交题的过程中,发现几个问题:碰到一个答案错误和一个段错误。如下:
针对这几个问题,我一 一叙述。
- 先上段错误。对段错误都很熟悉,主要的原因就是因为访问了不该访问的东西,导致段错误的发生。错误代码如下:
···
int N,M,K;
cin >> N>>M;
int i,j,z;
int edge[N][N];//使用邻接矩阵存边的信息
···
错误的原因是:如果顶点的序号是从 0 -> (N-1)
,那么我们可以使用edge[N][N]
作为存储。但是如果顶点的序号是从 1 -> N
,那么就必须是 edge[N+1][N+1]
,否则会出现段错误。在这里,我定义了一个maxn,并使用 maxn 作为存储大小 的范围。
- 再上第三个测试点的错误
这个点我找了好久,一直不知道是什么原因导致这个测试点过不去。后来奋战了好久,才知道没有对保存查询节点的set<int> query
进行清空导致出现set
中的数据未清空,然后遗留数据报错!