http://codeup.cn/problem.php?cid=100000620&pid=1

问题 B: 连通图

时间限制: 1 Sec  内存限制: 32 MB

题目描述

给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。

输入

每组数据的第一行是两个整数 n 和 m(0<=n<=1000)。n 表示图的顶点数目,m 表示图中边的数目。如果 n 为 0 表示输入结束。随后有 m 行数据,每行有两个值 x 和 y(0<x, y <=n),表示顶点 x 和 y 相连,顶点的编号从 1 开始计算。输入不保证这些边是否重复。

输出

对于每组输入数据,如果所有顶点都是连通的,输出"YES",否则输出"NO"。

样例输入

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

样例输出

YES
YES
NO

思路很简单,求连通块个数,判断是否为1?

并查集做法 AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int nmax=1010;
int father[nmax];
int isRoot[nmax];
 
int findFather(int u){
	if(u==father[u]) return u;
	else{
		int f=findFather(father[u]);
		father[u]=f;
		return f;
	}
} 
 
void Union(int u,int v){
	int fu=findFather(u);
	int fv=findFather(v);
	if(fu!=fv){
		father[fu]=fv;
	} 
}
 
void init(int n){
	for(int i=1;i<=n;i++){
		father[i]=i;
		isRoot[i]=0;
	}
}
 
int main(int argc, char** argv) {
	int n,m;//点数,边数
	while(cin>>n>>m){
		if(n==0){
			break;
		}
		memset(father,0,sizeof(father));
		memset(isRoot,0,sizeof(isRoot));
		init(n);
		int u,v;
		for(int i=0;i<m;i++){
			cin>>u>>v;
			Union(u,v);
		}
		int ans=0;
		for(int i=1;i<=n;i++){
			if(father[i]==i){
				ans++;
			}
		}
        if(ans==1){
        	printf("YES\n");
		}else{
			printf("NO\n");
		}
	} 
	return 0;
}

DFS做法 AC Code

DFS可解决本题,这题需要注意的是,每次输入样例读入前:邻接表要清零。

1、可以在每次输入样例读入前,清空邻接表。

2、也可以像下面的代码一样:每次遍历完一个点的所有相邻边,在DFS函数中清空邻接表。

       之前一直超时,或者出现了运行错误( 只过了50%数据???)的原因就是:没有G【u】.clear();

参考链接:点击链接

“不管是邻接矩阵还是邻接表,在访问完当前边准备向访问下一层时,删除当前边的数据(邻接矩阵),邻接表则在访问完一个顶点的所有邻接边之后再清除。G【u】.clear();”

以下代码 AC

//图的DFS遍历 计算连通块数 
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring> 
using namespace std; 
const int nmax=1010;
vector<int> G[nmax];
int vis[nmax];//1已被访问 0未被访问 

//遍历连通块 
void DFS(int u){
	vis[u]=1;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(vis[v]==0){//如果该节点未被访问,则深度遍历 
			DFS(v);
		} 
	}
	G[u].clear(); 
} 
int main(int argc, char** argv) {
	int n;//点数 
	int m;//边数
	while(cin>>n>>m){
		if(n==0){
			break;
		}
		memset(vis,0,sizeof(vis));
		int u,v;
		for(int i=0;i<m;i++){
			cin>>u>>v;
			G[u].push_back(v);
			G[v].push_back(u);
		} 
		int blk=0;
		//遍历整个图G
		for(int i=1;i<=n;i++){
			if(vis[i]==0){
				DFS(i);//访问i所在的连通块 
				blk++; 
			}
		} 
		//cout<<blk<<endl;
		if(blk==1){
			cout<<"YES"<<endl;
		}else{
			cout<<"NO"<<endl;
		}
	} 
	return 0;
}