列出连通集 (25 分)

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:
按照"{ v1 v2 … vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

本题如果题目没有要求按照序号从小到大的顺序遍历的话,完全可以利用vector或者链表组成的邻接表,但是因为有了这个要求,所以本题显然是要让读者用邻接矩阵去做的,但是有些读者,比如我,用邻接表用惯了,突然让我用邻接矩阵写就相当于要我的命,几乎都忘完了,所以,我想到了一种做法,也就是放弃vector改用set,因为set内部本身就是从小到大排序的,并且有关图的题也不可能会出现重复的顶点,所以,换成set是在是再好不过了,我把用vector的代码给注释掉了,大家可以对比一下看看都有什么不同的地方.

#include<iostream>
#include<set>
#include<queue>
using namespace std;
//vector<int> Adj[25];
set<int> Adj[25];
bool vis[25]={};
bool inq[25]={};
int n,m;
void dfs(int s){
	vis[s]=true;
	cout<<' '<<s;
	for(auto it=Adj[s].begin();it!=Adj[s].end();it++){
		if(vis[*it]==false){
			dfs(*it);
		}
	}
//	for(int i=0;i<Adj[s].size();i++){
//		if(vis[Adj[s][i]]==false){
//			dfs(Adj[s][i]);
//		}
//	}	
}
void bfs(int s){
	queue<int> q;
	inq[s]=true;
	q.push(s);
	while(!q.empty()){
		int t=q.front();
		cout<<' '<<t;
		q.pop();
		for(auto it=Adj[t].begin();it!=Adj[t].end();it++){
			if(inq[*it]==false){
				inq[*it]=true;
				q.push(*it);
			}
		}
//		for(int i=0;i<Adj[t].size();i++){
//			if(inq[Adj[t][i]]==false){
//				inq[Adj[t][i]]=true;
//				q.push(Adj[t][i]);
//			}
//		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=0,a,b;cin>>a>>b;i++){
		Adj[a].insert(b);
		Adj[b].insert(a);
//		Adj[a].push_back(b);
//		Adj[b].push_back(a);
	}	
	for(int i=0;i<n;i++){
		if(vis[i])continue;
		cout<<'{';
		dfs(i);
		cout<<" }\n";
	}
	for(int i=0;i<n;i++){
		if(inq[i])continue;
		cout<<'{';
		bfs(i);
		cout<<" }\n";
	}
}