并查集+DFS深度优先
1、并查集:
初始化
int fa[MAX];//用一个数组fa[]来存储每个元素的父节点
void init(int n)
{
for (int i = 1; i <= n; ++i)
fa[i] = i;//先将它们的父节点设为自己
}
查询
int find(int x)
{
if(fa[x] == x)
return x;
else
return find(fa[x]);
}
//或者在查询阶段**路径压缩**
int find(int x){
//返回x的祖宗节点
//加上路径压缩
if(fa[x]!=x)
fa[x]=find(fa[x]);
//每次如果当前节点不是根节点
//就递归寻找它父亲的根节点,顺便路径压缩
return fa[x];
//如果找到了根节点的话就返回,更新先前的递归
}
合并
void merge(int i, int j)
{
fa[find(i)] = find(j);
}
进一步优化,把简单树并到复杂树上
//**初始化**
//用一个数组rank[]记录每个根节点对应的树的深度,初始为1
void init(int n)
{
for (int i = 1; i <= n; ++i)
{
fa[i] = i;
rank[i] = 1;
}
}
合并
//合并时比较两个根节点,把rank较小者往较大者上合并
void merge(int i, int j)
{
int x = find(i), y = find(j); //先找到两个根节点
if (rank[x] <= rank[y])
fa[x] = y;
else
fa[y] = x;
if (rank[x] == rank[y] && x != y)
rank[y]++; //如果深度相同且根节点不同,则新的根节点的深度+1
}
DFS:1、递归 2、栈
深度优先搜索的步骤分为 1.递归下去 2.回溯上来
递归
int visited[N + 1] = { 0 };
void DFS(int start)//递归
{
visited[start] = 1;
cout << start << " ";
for (int i = 1; i <= N; i++)
{
if (!visited[i] && maze[start - 1][i - 1] == 1)
DFS(i);
}
}
非递归
int visited[N + 1] = { 0 };
void DFS(int start)
{
stack<int> s;
s.push(start);
visited[start] = 1;
while (!s.empty())
{
int v = s.top();
cout << v << " ";
s.pop();
for (int i = 1; i <= N; i++)
{
if (!visited[i] && maze[v - 1][i - 1] == 1 )
{
visited[i] = 1;
s.push(i);
}
}
}
}