ALDS1_11_D:Connected Components
题目:
https://cn.vjudge.net/problem/Aizu-ALDS1_11_D
代码如下:
1.dfs实现
#include<bits/stdc++.h>
using namespace std;
#define MAX 100005
#define NIL -1
int n;
int a[MAX],color[MAX];
vector<int> p[MAX];
void dfs(int r,int id)
{
stack<int> s;
s.push(r);
color[r] = id;
while(!s.empty())
{
int u = s.top();
s.pop();
for(int i = 0;i < p[u].size();i++)
{
int v = p[u][i];
if(color[v] == NIL)
{
color[v] = id;
s.push(v);
}
}
}
}
void assigncolor()
{
int id = 1;
for(int i = 0;i < n;i++) color[i] = NIL;
for(int i = 0;i < n;i++)
{
if(color[i] == NIL) dfs(i,id++);
}
}
int main()
{
int m,s,t,q;
scanf("%d%d",&n,&m);
for(int i = 0;i < m;i++)
{
scanf("%d%d",&s,&t);
p[s].push_back(t);
p[t].push_back(s);
}
assigncolor();
scanf("%d",&q);
for(int i = 0;i < q;i++)
{
scanf("%d%d",&s,&t);
if(color[s] == color[t]) cout << "yes" << endl;
else cout << "no" << endl;
}
return 0;
}
2.bfs实现
#include<bits/stdc++.h>
using namespace std;
#define MAX 105
#define NIL -1
int a[MAX][MAX],d[MAX];
int n;
void bfs(int s)
{
int v;
for(int i = 0;i < n;i++) d[i] = NIL;
queue<int> q;
q.push(s);
d[s] = 0;
while(!q.empty())
{
v = q.front();
q.pop();
for(int i = 0;i < n;i++)
{
if(d[i] != NIL) continue;
if(a[v][i] == 1)
{
q.push(i);
d[i] = d[v] + 1;
}
}
}
}
int main()
{
int u,k,v;
scanf("%d",&n);
for(int i = 0;i < n;i++)
{
scanf("%d%d",&u,&k);
u--;
for(int j = 0;j < k;j++)
{
scanf("%d",&v);
v--;
a[u][v] = 1;
}
}
bfs(0);
for(int i = 0;i < n;i++) cout << i + 1 << " " << d[i] << endl;
return 0;
}
此题要求输入邻接表来表示图,邻接表的实现这里用的是vector来完成的,首先给vector开一个数组,因为这里是无向稀疏图,所有当结点i和结点j相连接时,包含结点i的表中有结点j,包含结点j的表中也有结点i。
求图的连通分量时,需要以未访问的结点为起点循环执行深度优先搜索(或者是广度优先搜索),这里两种写法都写出来了。开始时,先把所有的结点编号都赋值为-1,随后在搜索过程中只要是把所有搜素到的点都赋值相同的值(这里指的是在同一轮搜索中),但是每轮搜索的结点编号赋值都是不一样的,编号值的种类就代表连通分量的个数,最后知道直接判断两个点的编号是否相同就可以得知两个结点是否可以抵达。