【SSL1759】连通分量【五种方法】

Description

求一个图的连通分量

Input

n 顶点数(<=100)
连接的边

Output

连通分量

Sample Input

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

Sample Output

4

分析

总的来讲,这题我分了5种做法:

1.DFS+邻接矩阵
2.DFS+邻接表
3.BFS+邻接矩阵
4.BFS+邻接表
5.BFS+邻接表+STL
方法一:用一个数组作为邻接矩阵存储,再DFS,要注意判断走过没有。
#include<iostream>
#include<cstdio>
using namespace std;
int n,x,y,a[101][101],p[101],ans,s;//a是矩阵
void dfs(int i)
{
	p[i]=1;
	for(int j=1;j<=n;j++)
	{
		if(a[i][j]&&!p[j])//看走过没
		{
			s++;//分量++
			dfs(j);
		}
	}
}
int main()
{
	cin>>n>>x>>y;
	while(x!=0&&y!=0)
	{
		a[x][y]=1;
		a[y][x]=1;
		cin>>x>>y;
	}
	for(int i=1;i<=n;i++)
	{
		if(p[i]==0)
		{
			s=1;
			dfs(i);
			ans=max(ans,s);//选择最大的
		}
		
	}
	cout<<ans;
	return 0;
} 
方法二:用DFS,但是用链表的方法存,搜索时就省了很多时间,不用一个一个过边。
#include<iostream>
#include<cstdio>
using namespace std;
int n,x,y,p[101],ans,s,k,b[101];
struct node
{
	int next,xx;//ss为连接的数,next和同一个点的另一条线
}a[10001];
int dfs(int i)
{
	p[i]=1;
	for(int j=b[i];j;j=a[j].next))//以now为起点的所有边
	{
		if(p[a[j].xx]==0)
		{
			s++;
			dfs(a[j].xx);
		}
	}
	return s;
}
int main()
{
	cin>>n>>x>>y;
	while(x!=0&&y!=0)
	{
    /*六行等于add(x,y),add(y,x)*/
		a[++k].xx=y;//下一个数
		a[k].next=b[x];//下一条边
		b[x]=k;//替换
		a[++k].xx=x;//反过来,做一遍(无向)
		a[k].next=b[y];
		b[y]=k;
		cin>>x>>y;
	}
	for(int i=1;i<=n;i++)
	{
		if(p[i]==0)
		{
			s=1;
			dfs(i);
			ans=max(ans,s);
		}
	}
	cout<<ans;
	return 0;
} 
方法三:同样是用邻接矩阵,但用BFS,从每一个位置开始,s记录数量,最后return s再选一个最大值。
#include<iostream>
#include<cstdio>
using namespace std;
int n,x,y,a[101][101],p[101],ans,s;
void bfs(int i)
{
	int h=0,t=1,st[101];
	st[1]=i;
	while(h<t)
	{
		h++;
		for(int j=1;j<=n;j++)
		{
			if(a[st[h]][j]&&p[j]==0)//是否可到,到过没
			{
				p[j]=1;
				s++;
				t++;
				st[t]=j;
			}
		}
	}
}
int main()
{
	cin>>n>>x>>y;
	while(x!=0&&y!=0)
	{
		a[x][y]=1;
		a[y][x]=1;
		cin>>x>>y;
	}
	for(int i=1;i<=n;i++)
	{
		if(p[i]==0)
		{
			s=0;
			bfs(i);
			ans=max(ans,s);
		}
		
	}
	cout<<ans;
	return 0;
} 
方法四:用bfs和邻接表,内容基本就是方法二和方法三的合成体,同时注意循环和判断。
#include<iostream>
#include<cstdio>
using namespace std;
int n,x,y,p[101],ans,s,k,b[101];
struct node
{
	int next,xx;
}a[10001];
int bfs(int i)
{
	int h=0,t=1,st[101];
	st[1]=i;
	p[i]=1;
	while(h<t)
	{
		h++;
		for(int j=b[st[h]];j;j=a[j].next)
		{
			if(!p[a[j].xx])
			{
				p[a[j].xx]=1;
				s++;t++;
				st[t]=a[j].xx;
			}
		}
	}
}
int main()
{
	cin>>n>>x>>y;
	while(x!=0&&y!=0)
	{
		a[++k].xx=y;
		a[k].next=b[x];
		b[x]=k;
		a[++k].xx=x;
		a[k].next=b[y];
		b[y]=k;
		cin>>x>>y;
	}
	for(int i=1;i<=n;i++)
	{
		if(p[i]==0)
		{
			s=1;
		    bfs(i);
			ans=max(ans,s);
		}
	}
	cout<<ans;
	return 0;
} 
方法五:和方法四的思路相同,但运用了一种鲜为 我知的技术——STL(queue)。把一些跟队列有关的语句用STL实现。
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,x,y,p[101],ans,s,k,b[101];
struct node
{
	int next,xx;
}a[10001];
int bfs(int i)
{
	int h=0,t=1;
    queue<int>st;
	st.push(i); //入队
	while(st.size())
	{
		int x=st.front();//取队首
		st.pop();//出队
		for(int j=b[x];j;j=a[j].next)
		{
			if(!p[a[j].xx])
			{
				p[a[j].xx]=1;
				s++;
				st.push(a[j].xx); 
			}
		}
	}
}
int main()
{
	cin>>n>>x>>y;
	while(x!=0&&y!=0)
	{
		a[++k].xx=y;
		a[k].next=b[x];
		b[x]=k;
		a[++k].xx=x;
		a[k].next=b[y];
		b[y]=k;
		cin>>x>>y;
	}
	for(int i=1;i<=n;i++)
	{
		if(p[i]==0)
		{
			s=0;
		    bfs(i);
			ans=max(ans,s);
		}
	}
	cout<<ans;
	return 0;
} 

搞掂五种方法啦!开森(/≧▽≦)/

发布了31 篇原创文章 · 获赞 23 · 访问量 898

猜你喜欢

转载自blog.csdn.net/dglyr/article/details/103539229
今日推荐