7-7 列出连通集(25 分) 【图的遍历】

本文介绍了一种使用深度优先搜索(DFS)和广度优先搜索(BFS)算法来找出无向图中所有连通集的方法。通过具体实例展示了如何从编号最小的顶点开始,递增地访问邻接点,最终列出图的所有连通部分。

7-7 列出连通集(25 分)

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式:

输入第1行给出2个整数N(0

#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <set>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <limits>

#define CLR(a) memset(a, 0, sizeof(a))
#define pb push_back

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair<string, int> psi;
typedef pair<string, string> pss;

const double PI = 3.14159265358979323846264338327;
const double E = exp(1);
const double eps = 1e-30;

const int INF = 0x3f3f3f3f;
const int maxn = 2e2 + 5;
const int MOD = 1e9 + 7;

int G[10][10];
int V[10];

int n, e;

void dfs(int x)
{
    V[x] = 1;
    printf("%d ", x);
    for (int i = 0; i < n; i++)
    {
        if (V[i] == 0 && G[x][i] == 1)
            dfs(i);
    }
}

queue <int>q;

void bfs()
{
    int len = q.size();
    for (int i = 0; i < len; i++)
    {
        int num = q.front();
        printf("%d ", num);
        q.pop();
        for (int j = 0; j < n; j++)
        {
            if (V[j] == 0 && G[num][j])
            {
                V[j] = 1;
                q.push(j);
            }
        }
    }
    if (q.size())
        bfs();
}

int main()
{
    CLR(G);
    CLR(V);
    scanf("%d%d", &n, &e);
    int x, y;
    for (int i = 0; i < e; i++)
    {
        scanf("%d%d", &x, &y);
        G[x][y] = 1;
        G[y][x] = 1;
    }
    for (int i = 0; i < n; i++)
    {
        if (V[i] == 0)
        {
            printf("{ ");
            dfs(i);
            printf("}\n");
        }
    }
    CLR(V);
    for (int i = 0; i < n; i++)
    {
        if (V[i] == 0)
        {
            printf("{ ");
            q.push(i);
            V[i] = 1;
            bfs();
            printf("}\n");
        }
    }
}






以下是使用 **C++** 实现的完整解决方案,用于解决“列出连通集”问题。我们使用 **深度优先搜索(DFS)** **广度优先搜索(BFS)** 来遍历无向图的所有连通量,并按照题目要求输出结果。 --- ```cpp #include <iostream> #include <vector> #include <queue> #include <set> #include <algorithm> using namespace std; // DFS 遍历函数 void dfs(int u, vector<bool>& visited, const vector<vector<int>>& graph, vector<int>& component) { visited[u] = true; component.push_back(u); // 按编号递增顺序访问邻接点(已排序) for (int v : graph[u]) { if (!visited[v]) { dfs(v, visited, graph, component); } } } // BFS 遍历函数 void bfs(int start, vector<bool>& visited, const vector<vector<int>>& graph, vector<int>& component) { queue<int> q; q.push(start); visited[start] = true; while (!q.empty()) { int u = q.front(); q.pop(); component.push_back(u); // 同样按编号递增顺序处理邻接点 for (int v : graph[u]) { if (!visited[v]) { visited[v] = true; q.push(v); } } } } int main() { int n, m; cin >> n >> m; // 建:邻接表表示 vector<vector<int>> graph(n); for (int i = 0; i < m; ++i) { int u, v; cin >> u >> v; graph[u].push_back(v); graph[v].push_back(u); } // 对每个顶点的邻接点按编号升序排列,确保访问顺序正确 for (int i = 0; i < n; ++i) { sort(graph[i].begin(), graph[i].end()); } vector<bool> visited(n, false); vector<vector<int>> dfsComponents, bfsComponents; // 使用 DFS 找出所有连通集 for (int i = 0; i < n; ++i) { if (!visited[i]) { vector<int> comp; dfs(i, visited, graph, comp); dfsComponents.push_back(comp); } } // 重置 visited 数组用于 BFS fill(visited.begin(), visited.end(), false); // 使用 BFS 找出所有连通集 for (int i = 0; i < n; ++i) { if (!visited[i]) { vector<int> comp; bfs(i, visited, graph, comp); bfsComponents.push_back(comp); } } // 输出 DFS 结果 for (const auto& comp : dfsComponents) { cout << "{ "; for (size_t i = 0; i < comp.size(); ++i) { cout << comp[i]; if (i != comp.size() - 1) cout << " "; } cout << " }" << endl; } // 输出 BFS 结果 for (const auto& comp : bfsComponents) { cout << "{ "; for (size_t i = 0; i < comp.size(); ++i) { cout << comp[i]; if (i != comp.size() - 1) cout << " "; } cout << " }" << endl; } return 0; } ``` --- ### ✅ **代码解释** 1. **的存储方式**: - 使用 `vector<vector<int>> graph(n)` 表示邻接表。 -是无向的,因此 `u -> v` `v -> u` 都要加入。 2. **排序邻接点**: - 每个节点的邻接点通过 `sort()` 排序,保证在 DFS/BFS 中“按编号递增顺序”访问。 3. **DFS 函数**: - 递归实现深度优先搜索,将访问到的节点加入当前连通量。 - 使用 `visited` 数组避免重复访问。 4. **BFS 函数**: - 使用队列实现广度优先搜索,逻辑清晰,逐层扩展。 5. **主函数流程**: - 构建 → 排序邻接点 → DFS 遍历所有连通集 → 重置 visited → BFS 遍历 → 输出。 6. **输出格式**: - 严格遵循 `{ v1 v2 ... vk }` 格式,空格隔,首尾有空格但无多余符号。 --- ### 📌 输入样例析 输入: ``` 8 6 0 7 0 1 2 0 4 1 2 4 3 5 ``` 构建后,连通关系为: - 连通集1: 0,1,2,4,7(互相可达) - 连通集2: 3,5 - 孤立点: 6 所以输出三个集合。 --- ### ✅ 输出样例匹配 ``` { 0 1 4 2 7 } { 3 5 } { 6 } { 0 1 2 7 4 } { 3 5 } { 6 } ``` 注意:DFS BFS 的顺序不同是因为遍历策略不同,但都从最小编号出发,且邻接点按升序处理。 --- ### ⚠️ 注意事项 - 节点编号从 `0` 开始。 - 即使是孤立点(如 6),也要作为一个单独的连通集输出。 - 必须对每个顶点的邻接列表排序,否则访问顺序可能错误。 - 时间复杂度:O(n + m),空间复杂度:O(n + m),满足题目限制。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值