图论:邻接表存储的二叉树(C)
图论:邻接表存储的二叉树(C)

图论:邻接表存储的二叉树(C)

一、冗余连接

1、题目描述

树可以看成是一个连通且无环无向图。给定一个图,该图从一棵 n 个节点(节点值 1~n)的树中添加一条边后获得。添加的边的两个不同顶点编号在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edgesedges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges最后出现的那个。

2、思路

遍历每一条边,在加入这条边之前,先用 DFS/BFS 检测两个节点是否已经连通。如果已经连通,说明这条边就是多余的。

3、算法求解

(1)DFS做法

(主函数)

(DFS函数)

蓝桥杯必会写法:

#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>

#define MAX_NODES 1005

// 初始化邻接矩阵(直接全局定义)
int adj[1001][1001];

bool canReachDFS(int curr, int target, bool* visited) {
    // 找到了目标,返回 true
    if (curr == target) return true;

    // 标记当前节点已访问
    visited[curr] = true;

    // 遍历当前节点的所有邻居
    for (int i = 1; i < 1001; i++) {

        if (adj[curr][i] == 1) {
            int neighbor = i;
            // 如果邻居还没访问过,递归去查
            if (!visited[neighbor]) {
                if (canReachDFS(neighbor, target, visited)) {
                    return true;
                }
            }
        }
    }

    return false;
}

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* findRedundantConnection(int** edges, int edgesSize, int* edgesColSize, int* returnSize) {
    int* result = (int*)malloc(2 * sizeof(int));
    *returnSize = 2;

    memset(adj, 0, sizeof(adj));
    

    for (int i = 0; i < edgesSize; i++) {
        int u = edges[i][0];
        int v = edges[i][1];

        // 每次 DFS 前重置 visited 数组
        bool visited[MAX_NODES] = {false};

        // 核心:用 DFS 检测 u 到 v 是否存在路径
        if (canReachDFS(u, v, visited)) {
            result[0] = u;
            result[1] = v;
            return result;
        }

        // 没连通,则加边
        adj[u][v] = 1;
        adj[v][u] = 1;
    }

    return result;
}

(2)BFS做法

(主函数)

可见,BFS的逻辑和DFS的逻辑相同。

(BFS函数)

注意:要掌握BFS中队列的存储方法。

二、邻接表存储二叉树完整做法

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注