树的最小支配集

/**
    最小支配集,就是图中用最少的点覆盖其它所有点
    如果用选A点覆盖,则与A点相连的点都被覆盖,大致
    就是这样
    百度里面搜到一道题
    有一个图G,现在希望在一些点建立控制站,每个控制站能控制与它相临的点(直接相连),
    现在希望有选择的在一些点建立控制站,使得以最小得控制站数,控制所有的点

    图的最小支配集是NP 问题,我只会树的最小支配集模板,就是
    图G 是树形结构

    判断树的最小支配集,条件如下
    1、选一结点为根后序遍历
    2、遍历过程中,如果该结点没被覆盖,该结点的父亲结点没被覆盖,且
    该结点的子结点中没有被覆盖的,则该结点的父亲结点即为一覆盖点

    就上面两个条件即可实现,证明不会,自己画画就能懂

    现在用vector 存边来写下

    #include <vector>

    vector<int> adj[M];
    bool vis[M], over[M];
    int ans;

    //初始化: vis, over, ans = 0

    //调用dfs(1, 1), 选 1 为根节点

    void dfs(int u, int fa) {
    //根节点判断可省去判断父亲结点
        vis[u] = 1;
        bool flag = false;
        for (int i=0; i<adj[u].size(); i++) {
            int v = adj[u][i];
            if (!vis[v]) {
                dfs(v, u);
                flag = flag || over[v];
            }
        }
        if (!over[fa] && !flag && !over[u]) {
        //父亲结点没覆盖,没子结点覆盖,本身没覆盖,3个条件
            over[fa] = 1;
            ans++;
        }
    }

    ans即为最小支配集得个数,over[x] 表示x点被覆盖

    POJ 3659

*/

收藏于 2012-01-20
来自于百度空间

### Python 实现图论中的最小支配集算法 在图论中,最小支配集是一个经典的 NP 完全问题。然而,在特定情况下(如形结构),可以采用贪心策略或其他优化方法来高效解决问题[^4]。 以下是基于最小支配集算法的一个具体实现: #### 输入定义 输入为一棵无向 `G` 的邻接表表示形式。假设节点编号从 `0` 到 `n-1`。 #### 输出定义 返回一个集合,其中包含构成最小支配集的所有节点。 --- ```python from collections import defaultdict, deque def minimum_dominating_set(tree): """ 计算给定最小支配集。 参数: tree (dict): 邻接表表示的 返回: set: 最小支配集中的节点集合 """ n = len(tree) state = [-1] * n # 初始化状态数组:-1 表示未访问,0 表示不选,1 表示选 queue = deque() # 找到叶子节点并初始化队列 for node in range(n): if len(tree[node]) == 1 and node != 0: # 叶子节点(根除外) queue.append(node) while queue: current_node = queue.popleft() if state[current_node] == -1: # 如果当前节点未被标记 parent = list(tree[current_node])[0] # 获取父节点 if state[parent] == -1: # 如果父节点未被标记,则选择父节点加入支配集 state[parent] = 1 # 将父节点的所有邻居设置为已覆盖 for neighbor in tree[parent]: if state[neighbor] == -1: state[neighbor] = 0 queue.append(parent) # 将父节点重新入队以便进一步处理 dominating_set = {i for i in range(n) if state[i] == 1} return dominating_set # 测试用例 if __name__ == "__main__": # 构建一颗简单的 adj_list = { 0: [1, 2], 1: [0, 3, 4], 2: [0], 3: [1], 4: [1] } result = minimum_dominating_set(adj_list) print("Minimum Dominating Set:", result) ``` --- #### 关键点解释 1. **状态设计**: 使用 `-1`, `0`, 和 `1` 分别表示节点的状态: - `-1`: 节点尚未处理; - `0`: 节点已被其他节点覆盖; - `1`: 节点被选入支配集中。 2. **贪心策略**: 对于每一个叶节点,如果其父节点还未被选择,则将其父节点纳入支配集,并更新相关联的兄弟节点状态。 3. **复杂度分析**: - 时间复杂度为 \(O(V + E)\),适用于稀疏图的情况,尤其是结构。 --- ### 注意事项 上述代码仅针对结构进行了优化。对于一般图而言,由于最小支配集问题是 NP 完全问题,因此无法通过简单的方法获得精确解。通常需要借助启发式算法或近似算法来获取较优的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值