Time Limit:1000MS Memory Limit:65536K
Total Submit:481 Accepted:290
n 顶点数(<=100)
边
连通分量
8
6 3
1 2
2 5
5 4
4 1
8 7
0 0
4
图论基本例题,连通分量指的是最大连通数,这里提供五种方法:
a[x][y]=1表示x到y存在路径,无向图所以a[y][x]也要标记为1。
邻接矩阵存储路径,枚举每个没访问过的点开始 dfs,求出连通分量。
#include
#include
#include
#include
#include
using namespace std;
int n,x,y,a[101][101],b[101],t,head,tail,c[201],w,s,ans=0;
void in(){
cin>>n;
do{
cin>>x>>y;
if(!x) break;
a[x][y]=1;
a[y][x]=1;
//邻接矩阵标记路径
}while(1);
}
int dfs(int f){
for(int i=1;i<=n;i++){
//枚举每个点,若当前的点与该点存在路径且没访问过,则往该点搜索
if(a[f][i]&&!b[i]){
s++;
b[i]=1;
dfs(i);
}
}return s;
}
int main(){
in();
for(int i=1;i<=n;i++){
s=1;
if(!b[i]){
b[i]=1;
ans=max(ans,dfs(i));
}
}cout<<ans;
}
邻接矩阵存储路径,枚举每个没访问过的点开始 bfs,求出连通分量。
#include
#include
#include
#include
#include
using namespace std;
int n,x,y,a[101][101],b[101],t,head,tail,c[201],w,s,ans;
void in(){
cin>>n;
do{
cin>>x>>y;
if(!x) break;
a[x][y]=1;
a[y][x]=1;
//邻接矩阵标记路径
}while(1);
}
int bfs(int f){
head=0;tail=1;
//head:队首, tail:队尾
c[1]=f;
do{
head++;w=c[head];
for(int i=1;i<=n;i++){
//枚举每个点,若当前的点与该点存在路径且没访问过,则将该点加入队列
if(a[w][i]&&!b[i]){
b[i]=1;
c[++tail]=i;
s++;
}
}
}while(head!=tail);
return s;
}
int main(){
in();
for(int i=1;i<=n;i++){
s=1;
if(!b[i]){
b[i]=1;
ans=max(ans,bfs(i));
}
}cout<<ans;
}
邻接表 | |
---|---|
e[i].y | 表示路径i连通的一个点y |
e[i].nt | 表示连接另一个点x的下一条路径存储在e中的下标 |
h[x] | 表示连接点x的路径的下标 |
cin>>x>>y;
e[++l].y=y;e[l].nt=h[x];h[x]=l;
e[++l].y=x;e[l].nt=h[y];h[y]=l;
// 无向图,所以路径反过来也要存储
邻接表存储路径,枚举每个没访问过的点开始 dfs,求出连通分量。
dfs:枚举每个当前点能通且没访问过的点搜索下去,
#include
#include
#include
#include
#include
using namespace std;
int n,x,y,b[101],t,head,tail,c[201],w,s,ans=0,l,h[10001];
struct haha{
int y,nt;
}e[11000];
void in(){
cin>>n;
do{
cin>>x>>y;
if(!x) break;
e[++l].y=y;e[l].nt=h[x];h[x]=l;
e[++l].y=x;e[l].nt=h[y];h[y]=l;
//邻接表存储路径
}while(1);
}
int dfs(int f){
for(int i=h[f];i;i=e[i].nt){
//枚举每个当前点能通且没访问过的点搜索下去
if(!b[e[i].y]){
b[e[i].y]=1;
s++;
dfs(e[i].y);
}
}return s;
}
int main(){
in();
for(int i=1;i<=n;i++){
s=1;
if(!b[i]){
b[i]=1;
ans=max(ans,dfs(i));
}
}cout<<ans;
}
跟dfs一样,枚举每个没访问过的点开始 bfs,枚举每个当前点能通且没访问过的点加入队列,求出连通分量。
#include
#include
#include
#include
#include
using namespace std;
int n,x,y,b[101],t,head,tail,c[201],w,s,ans=0,l,h[10001];
struct haha{
int y,nt;
}e[11000];
void in(){
cin>>n;
do{
cin>>x>>y;
if(!x) break;
e[++l].y=y;e[l].nt=h[x];h[x]=l;
e[++l].y=x;e[l].nt=h[y];h[y]=l;
}while(1);
}
int bfs(int f){
head=0;tail=1;
c[1]=f;
do{
head++;w=c[head];
for(int i=h[w];i;i=e[i].nt){
if(!b[e[i].y]){
//枚举每个当前点能通且没访问过的点加入队列
b[e[i].y]=1;
c[++tail]=e[i].y;
s++;
}
}
}while(head!=tail);
return s;
}
int main(){
in();
for(int i=1;i<=n;i++){
s=1;
if(!b[i]){
b[i]=1;
ans=max(ans,bfs(i));
}
}cout<<ans;
}
使用queue自带队列
#include
#include
#include
#include
#include
using namespace std;
int n,x,y,b[101],t,head,tail,c[201],w,s,ans=0,l,h[10001];
struct haha{
int y,nt;
}e[11000];
void in(){
cin>>n;
do{
cin>>x>>y;
if(!x) break;
e[++l].y=y;e[l].nt=h[x];h[x]=l;
e[++l].y=x;e[l].nt=h[y];h[y]=l;
}while(1);
}
int bfs(int f){
queue<int> c;//定义队列
c.push(f);//推入f
do{
w=c.front();//取队首
for(int i=h[w];i;i=e[i].nt){
if(!b[e[i].y]){
b[e[i].y]=1;
c.push(e[i].y);
s++;
}
}c.pop();//弹出队首
}while(!c.empty());//若队列非空,则继续循环
return s;
}
int main(){
in();
for(int i=1;i<=n;i++){
s=1;
if(!b[i]){
b[i]=1;
ans=max(ans,bfs(i));
}
}cout<<ans;
}