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;
}