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.总结

在交题的过程中,发现几个问题:碰到一个答案错误和一个段错误。如下:
PAT 1122 C++ 版_# PAT
针对这几个问题,我一 一叙述。

  • 先上段错误。对段错误都很熟悉,主要的原因就是因为访问了不该访问的东西,导致段错误的发生。错误代码如下:
···
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中的数据未清空,然后遗留数据报错!