华为OD机试 - 软件依赖树 - 广度优先搜索BFS(Python/JS/C/C++ 新系统 200分)

在这里插入图片描述

华为OD机试 新系统 统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

一、题目描述

在软件项目开发里涉及不同版本组件引用,组件依赖组件,形成一棵依赖树(从根节点深层展开);请编写一段代码,对当前项目的组件依赖关系进行分析,按项目组件依赖顺序输出最终有效的组件版本列表;
说明如下:

  1. 从根节点开始按依赖顺序输出组件列表,项目上层组件依赖先输出,如果同层依赖则父组件先出现的优先输出,父组件相同的按依赖出现顺序输出,如:项目依赖组件【b,a】,a依赖【c,d】,b依赖【e】,输出顺序为 b,a,e,c,d;
  2. 组件去重:依赖组件如多次出现,只保留第一次出现的顺序位置;
  3. 同一组件如有不同版本,以首次依赖的组件版本作为输出;

二、输入描述

  • 参数1:项目直属依赖 directDeps,格式:组件名:版本号:排除组件列表,如:a:v1:表示项目依赖a组件,版本为v1,无排除组件;

  • 参数2:全局组件依赖 depRules,格式:组件名:依赖组件名:依赖组件版本号:排除组件列表",如:a:b:v2:c,表示a组件依赖b组件v2版本,须排除b组件依赖的c组件子树;

输入列表顺序为依赖声明顺序;组件名、版本号由字母数字组成,非空;输入保证同一组件不同版本依赖相同;排除组件列表以半角逗号分隔,格式如:“a,b”,排除列表可为空,输入保证排除列表不会出现",b"或"a,"格式;

三、输出描述

符合依赖顺序要求的项目依赖组件列表,格式:组件名:版本号

四、测试用例

测试用例1:

1、输入

a:v1:

2、输出

a:v1

3、说明

没有任何间接依赖,所以直接输出 a:v1。

测试用例2:

1、输入

a:v1: b:v1:
a:c:v1: b:d:v1: d:c:v2:

2、输出

a:v1 b:v1 c:v1 d:v1

3、说明

第1层:
a:v1 b:v1

第2层:
a -> c:v1
b -> d:v1

得到:a b c d

之后:d -> c:v2

但 c 已经以 v1 第一次出现,所以忽略 c:v2。

五、解题思路

本题的核心是按照依赖树的层级顺序输出组件,因此采用 BFS(广度优先搜索) 遍历依赖关系,而不是 DFS。先把项目的直属依赖按输入顺序加入队列,再逐层处理每个组件的子依赖,这样可以保证“上层组件优先、同层按父组件出现顺序、同一父组件按依赖声明顺序”这一输出要求。

主要采用了以下数据结构:

邻接表 Map<String, List>:保存每个组件对应的依赖组件列表。List 可以保留依赖声明的原始顺序,适合表示组件依赖关系。

队列 Queue:用于 BFS 层序遍历,保证先处理上层组件,再处理下一层组件。

LinkedHashMap:保存组件第一次出现时的版本及顺序。它既可以实现组件去重,又能保留第一次插入顺序,因此可以满足“同一组件只保留第一次出现的位置和版本”的要求。

HashSet:保存当前依赖路径上生效的排除组件,查询某组件是否被排除的效率较高。

算法处理时,每遇到一个新的组件,先判断它是否被当前依赖路径排除;如果没有被排除,再判断是否已经出现过。只有第一次出现的组件才加入结果和 BFS 队列,并将当前依赖边上的排除项合并后继续向其子树传递。

整体上可以理解为:

构建依赖邻接表
        ↓
直属依赖按顺序加入 BFS 队列
        ↓
逐层遍历依赖关系
        ↓
排除当前路径不允许的组件
        ↓
LinkedHashMap 去重并保留首次版本
        ↓
按首次出现顺序输出

在不考虑排除集合复制开销的情况下,主体遍历的时间复杂度约为 O(V + E),其中 V 是组件数量,E 是依赖关系数量;空间复杂度约为 O(V + E)。

六、Python算法源码

from collections import defaultdict, deque
import sys


def parse_exclusions(text):
    """
    把逗号分隔的排除列表转换成集合。

    ""      -> set()
    "a,b"   -> {"a", "b"}
    """
    return set(text.split(',')) if text else set()


def main():
    lines = sys.stdin.read().splitlines()

    # 第一行直属依赖,第二行全局依赖规则
    direct_line = lines[0].strip() if len(lines) >= 1 else ""
    rule_line = lines[1].strip() if len(lines) >= 2 else ""

    # rules[parent] 按声明顺序保存子依赖
    rules = defaultdict(list)

    if rule_line:
        for item in rule_line.split():
            parts = item.split(':')

            parent = parts[0]
            child = parts[1]
            version = parts[2]

            exclusions = parse_exclusions(
                parts[3] if len(parts) > 3 else ""
            )

            rules[parent].append(
                (child, version, exclusions)
            )

    """
    Python 3.7+ 的 dict 保证插入顺序。

    所以 selected 同时负责:
    1. 全局组件去重;
    2. 保存第一次出现的版本;
    3. 保存最终输出顺序。
    """
    selected = {}

    # BFS 队列
    queue = deque()

    if direct_line:
        for item in direct_line.split():
            parts = item.split(':')

            name = parts[0]
            version = parts[1]

            exclusions = parse_exclusions(
                parts[2] if len(parts) > 2 else ""
            )

            if name not in selected:
                selected[name] = version
                queue.append(
                    (name, exclusions)
                )

    """
    BFS 保证:
    上层组件优先;
    同层按照父组件出现顺序;
    同父组件按照依赖声明顺序。
    """
    while queue:
        parent, active_exclusions = queue.popleft()

        for child, version, edge_exclusions in rules.get(parent, []):

            # 当前依赖路径已经排除 child,则整个 child 子树跳过
            if child in active_exclusions:
                continue

            # 第一次出现的版本和位置已经确定
            if child in selected:
                continue

            selected[child] = version

            # 将当前依赖边新增的排除项继续传递到 child 子树
            child_exclusions = (
                active_exclusions | edge_exclusions
            )

            queue.append(
                (child, child_exclusions)
            )

    print(
        ' '.join(
            f'{name}:{version}'
            for name, version in selected.items()
        )
    )


if __name__ == '__main__':
    main()

七、JavaScript算法源码

const fs = require('fs');

function parseExclusions(text) {
    return text
        ? new Set(text.split(','))
        : new Set();
}

const lines = fs
    .readFileSync(0, 'utf8')
    .split(/\r?\n/);

const directLine = (lines[0] || '').trim();
const ruleLine = (lines[1] || '').trim();

/*
 * rules:
 *
 * parent -> [
 *     { child, version, exclusions },
 *     ...
 * ]
 *
 * 数组能够保证同一父组件的依赖声明顺序。
 */
const rules = new Map();

if (ruleLine) {
    for (const item of ruleLine.split(/\s+/)) {

        const parts = item.split(':');

        const parent = parts[0];
        const child = parts[1];
        const version = parts[2];

        const exclusions =
            parseExclusions(parts[3] || '');

        if (!rules.has(parent)) {
            rules.set(parent, []);
        }

        rules.get(parent).push({
            child,
            version,
            exclusions
        });
    }
}

/*
 * JavaScript 的 Map 保证插入顺序。
 *
 * selected 同时负责:
 * 1. 去重;
 * 2. 保存第一次出现版本;
 * 3. 保存输出顺序。
 */
const selected = new Map();

/*
 * 使用数组 + head 实现队列。
 *
 * 不直接使用 shift(),
 * 避免频繁移动数组元素造成额外性能开销。
 */
const queue = [];
let head = 0;

if (directLine) {

    for (const item of directLine.split(/\s+/)) {

        const parts = item.split(':');

        const name = parts[0];
        const version = parts[1];

        const exclusions =
            parseExclusions(parts[2] || '');

        if (!selected.has(name)) {

            selected.set(name, version);

            queue.push({
                name,
                activeExclusions: exclusions
            });
        }
    }
}

// BFS 分层遍历依赖关系
while (head < queue.length) {

    const {
        name: parent,
        activeExclusions
    } = queue[head++];

    const children =
        rules.get(parent) || [];

    for (const edge of children) {

        /*
         * 当前路径已经排除该组件,
         * 则整个组件子树都不能进入。
         */
        if (activeExclusions.has(edge.child)) {
            continue;
        }

        /*
         * 全局去重:
         * 第一次出现决定最终位置和版本。
         */
        if (selected.has(edge.child)) {
            continue;
        }

        selected.set(
            edge.child,
            edge.version
        );

        /*
         * 子节点继承祖先的排除规则,
         * 并加入当前依赖边新增的排除规则。
         */
        const childExclusions =
            new Set(activeExclusions);

        for (const x of edge.exclusions) {
            childExclusions.add(x);
        }

        queue.push({
            name: edge.child,
            activeExclusions: childExclusions
        });
    }
}

const result = [];

for (const [name, version] of selected) {
    result.push(`${name}:${version}`);
}

console.log(result.join(' '));

八、C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>


typedef struct {
    char **data;
    int size;
    int cap;
} StrSet;


typedef struct {
    char *child;
    char *version;
    StrSet exclusions;
} Edge;


typedef struct {
    char *parent;

    Edge *edges;
    int size;
    int cap;
} RuleGroup;


typedef struct {
    char *name;
    char *version;
} Selected;


typedef struct {
    char *name;

    // 当前依赖路径累计生效的排除组件
    StrSet activeExclusions;
} Node;


/* 自己实现字符串复制,避免依赖非标准 strdup。 */
static char *dupStr(const char *s) {

    size_t n = strlen(s) + 1;

    char *p = (char *) malloc(n);

    if (p != NULL) {
        memcpy(p, s, n);
    }

    return p;
}


/*
 * 标准 C 动态读取一整行。
 * 不依赖 POSIX getline。
 */
static char *readLine(void) {

    int cap = 128;
    int len = 0;

    char *s =
            (char *) malloc(
                    (size_t) cap
            );

    int ch;

    if (s == NULL) {
        exit(1);
    }

    while ((ch = getchar()) != EOF
            && ch != '\n') {

        if (ch == '\r') {
            continue;
        }

        if (len + 1 >= cap) {

            cap *= 2;

            s = (char *) realloc(
                    s,
                    (size_t) cap
            );

            if (s == NULL) {
                exit(1);
            }
        }

        s[len++] = (char) ch;
    }

    s[len] = '\0';

    return s;
}


/*
 * 获取当前行中的下一个空白分隔字符串。
 *
 * 例如:
 * a:v1: b:v1:
 *
 * 依次取得:
 * a:v1:
 * b:v1:
 */
static char *nextToken(char **cursor) {

    char *p = *cursor;

    while (*p
            && isspace(
                    (unsigned char) *p
            )) {

        ++p;
    }

    if (!*p) {
        *cursor = p;
        return NULL;
    }

    char *start = p;

    while (*p
            && !isspace(
                    (unsigned char) *p
            )) {

        ++p;
    }

    if (*p) {
        *p++ = '\0';
    }

    *cursor = p;

    return start;
}


static void setInit(StrSet *s) {

    s->data = NULL;
    s->size = 0;
    s->cap = 0;
}


static int setContains(
        const StrSet *s,
        const char *x) {

    int i;

    for (i = 0; i < s->size; ++i) {

        if (strcmp(
                s->data[i],
                x
        ) == 0) {

            return 1;
        }
    }

    return 0;
}


static void setAdd(
        StrSet *s,
        const char *x) {

    if (setContains(s, x)) {
        return;
    }

    if (s->size == s->cap) {

        s->cap =
                s->cap == 0
                ? 4
                : s->cap * 2;

        s->data =
                (char **) realloc(
                        s->data,
                        sizeof(char *)
                                * (size_t) s->cap
                );

        if (s->data == NULL) {
            exit(1);
        }
    }

    s->data[s->size++] =
            dupStr(x);
}


static StrSet setCopy(
        const StrSet *src) {

    StrSet dst;

    int i;

    setInit(&dst);

    for (i = 0;
         i < src->size;
         ++i) {

        setAdd(
                &dst,
                src->data[i]
        );
    }

    return dst;
}


static void setMerge(
        StrSet *dst,
        const StrSet *src) {

    int i;

    for (i = 0;
         i < src->size;
         ++i) {

        setAdd(
                dst,
                src->data[i]
        );
    }
}


static void setFree(StrSet *s) {

    int i;

    for (i = 0;
         i < s->size;
         ++i) {

        free(s->data[i]);
    }

    free(s->data);
}


/*
 * 把:
 *
 * a,b,c
 *
 * 解析成排除集合。
 */
static StrSet parseExclusions(
        const char *text) {

    StrSet result;

    char *copy;
    char *p;
    char *start;

    setInit(&result);

    if (text == NULL
            || *text == '\0') {

        return result;
    }

    copy = dupStr(text);

    p = copy;
    start = p;

    while (1) {

        if (*p == ','
                || *p == '\0') {

            char saved = *p;

            *p = '\0';

            setAdd(
                    &result,
                    start
            );

            if (saved == '\0') {
                break;
            }

            start = p + 1;
        }

        ++p;
    }

    free(copy);

    return result;
}


/*
 * 按固定字段数量切分 ':'。
 *
 * 必须保留末尾空字段:
 *
 * a:v1:
 *
 * -> a
 * -> v1
 * -> ""
 */
static void splitFields(
        char *item,
        char **parts,
        int count) {

    int i;
    int j;

    char *p = item;

    for (i = 0;
         i < count - 1;
         ++i) {

        char *colon;

        parts[i] = p;

        colon = strchr(p, ':');

        if (colon == NULL) {

            p += strlen(p);

            for (j = i + 1;
                 j < count;
                 ++j) {

                parts[j] = p;
            }

            return;
        }

        *colon = '\0';

        p = colon + 1;
    }

    parts[count - 1] = p;
}


static RuleGroup *findGroup(
        RuleGroup *groups,
        int groupCount,
        const char *parent) {

    int i;

    for (i = 0;
         i < groupCount;
         ++i) {

        if (strcmp(
                groups[i].parent,
                parent
        ) == 0) {

            return &groups[i];
        }
    }

    return NULL;
}


static int selectedIndex(
        Selected *selected,
        int count,
        const char *name) {

    int i;

    for (i = 0;
         i < count;
         ++i) {

        if (strcmp(
                selected[i].name,
                name
        ) == 0) {

            return i;
        }
    }

    return -1;
}


int main(void) {

    char *directLine = readLine();
    char *ruleLine = readLine();

    RuleGroup *groups = NULL;

    int groupCount = 0;
    int groupCap = 0;

    char *cursor = ruleLine;
    char *item;


    /*
     * 构建依赖邻接表。
     * 每个父组件的 edges 数组保持输入声明顺序。
     */
    while ((item = nextToken(
            &cursor)) != NULL) {

        char *parts[4];

        RuleGroup *g;
        Edge *e;

        splitFields(
                item,
                parts,
                4
        );

        g = findGroup(
                groups,
                groupCount,
                parts[0]
        );

        if (g == NULL) {

            if (groupCount
                    == groupCap) {

                groupCap =
                        groupCap == 0
                        ? 4
                        : groupCap * 2;

                groups =
                        (RuleGroup *)
                                realloc(
                                        groups,
                                        sizeof(RuleGroup)
                                                * (size_t) groupCap
                                );

                if (groups == NULL) {
                    exit(1);
                }
            }

            g = &groups[groupCount++];

            g->parent =
                    dupStr(parts[0]);

            g->edges = NULL;
            g->size = 0;
            g->cap = 0;
        }

        if (g->size == g->cap) {

            g->cap =
                    g->cap == 0
                    ? 4
                    : g->cap * 2;

            g->edges =
                    (Edge *) realloc(
                            g->edges,
                            sizeof(Edge)
                                    * (size_t) g->cap
                    );

            if (g->edges == NULL) {
                exit(1);
            }
        }

        e = &g->edges[g->size++];

        e->child =
                dupStr(parts[1]);

        e->version =
                dupStr(parts[2]);

        e->exclusions =
                parseExclusions(
                        parts[3]
                );
    }


    Selected *selected = NULL;

    int selCount = 0;
    int selCap = 0;


    /*
     * 动态数组实现 BFS 队列。
     * head 表示当前队首位置。
     */
    Node *queue = NULL;

    int qSize = 0;
    int qCap = 0;
    int head = 0;


    cursor = directLine;

    while ((item = nextToken(
            &cursor)) != NULL) {

        char *parts[3];

        splitFields(
                item,
                parts,
                3
        );

        if (selectedIndex(
                selected,
                selCount,
                parts[0]
        ) < 0) {

            if (selCount
                    == selCap) {

                selCap =
                        selCap == 0
                        ? 4
                        : selCap * 2;

                selected =
                        (Selected *)
                                realloc(
                                        selected,
                                        sizeof(Selected)
                                                * (size_t) selCap
                                );

                if (selected == NULL) {
                    exit(1);
                }
            }

            selected[selCount].name =
                    dupStr(parts[0]);

            selected[selCount].version =
                    dupStr(parts[1]);

            ++selCount;


            if (qSize == qCap) {

                qCap =
                        qCap == 0
                        ? 4
                        : qCap * 2;

                queue =
                        (Node *) realloc(
                                queue,
                                sizeof(Node)
                                        * (size_t) qCap
                        );

                if (queue == NULL) {
                    exit(1);
                }
            }

            queue[qSize].name =
                    dupStr(parts[0]);

            queue[qSize]
                    .activeExclusions =
                    parseExclusions(
                            parts[2]
                    );

            ++qSize;
        }
    }


    /*
     * BFS 分层遍历。
     */
    while (head < qSize) {

        Node *parent =
                &queue[head++];

        RuleGroup *g =
                findGroup(
                        groups,
                        groupCount,
                        parent->name
                );

        int i;

        if (g == NULL) {
            continue;
        }

        for (i = 0;
             i < g->size;
             ++i) {

            Edge *e =
                    &g->edges[i];

            /*
             * 当前路径已经排除这个组件,
             * 则它以及整个子树都跳过。
             */
            if (setContains(
                    &parent->activeExclusions,
                    e->child)) {

                continue;
            }

            /*
             * 全局只保留第一次出现。
             */
            if (selectedIndex(
                    selected,
                    selCount,
                    e->child
            ) >= 0) {

                continue;
            }


            if (selCount
                    == selCap) {

                selCap =
                        selCap == 0
                        ? 4
                        : selCap * 2;

                selected =
                        (Selected *)
                                realloc(
                                        selected,
                                        sizeof(Selected)
                                                * (size_t) selCap
                                );

                if (selected == NULL) {
                    exit(1);
                }
            }

            selected[selCount].name =
                    dupStr(e->child);

            selected[selCount].version =
                    dupStr(e->version);

            ++selCount;


            if (qSize == qCap) {

                qCap =
                        qCap == 0
                        ? 4
                        : qCap * 2;

                queue =
                        (Node *) realloc(
                                queue,
                                sizeof(Node)
                                        * (size_t) qCap
                        );

                if (queue == NULL) {
                    exit(1);
                }
            }

            queue[qSize].name =
                    dupStr(e->child);

            /*
             * 子节点继承父节点当前生效的排除规则,
             * 再合并当前依赖边自己的排除项。
             *
             * 排除只沿当前依赖子树传播,
             * 不影响其他独立路径。
             */
            queue[qSize]
                    .activeExclusions =
                    setCopy(
                            &parent->activeExclusions
                    );

            setMerge(
                    &queue[qSize]
                            .activeExclusions,
                    &e->exclusions
            );

            ++qSize;
        }
    }


    /*
     * selected 的插入顺序
     * 就是最终输出顺序。
     */
    {
        int i;

        for (i = 0;
             i < selCount;
             ++i) {

            if (i > 0) {
                putchar(' ');
            }

            printf(
                    "%s:%s",
                    selected[i].name,
                    selected[i].version
            );
        }

        putchar('\n');
    }


    /* 释放动态内存 */
    {
        int i;
        int j;

        for (i = 0;
             i < groupCount;
             ++i) {

            free(groups[i].parent);

            for (j = 0;
                 j < groups[i].size;
                 ++j) {

                free(
                        groups[i]
                                .edges[j]
                                .child
                );

                free(
                        groups[i]
                                .edges[j]
                                .version
                );

                setFree(
                        &groups[i]
                                .edges[j]
                                .exclusions
                );
            }

            free(groups[i].edges);
        }

        free(groups);


        for (i = 0;
             i < selCount;
             ++i) {

            free(selected[i].name);
            free(selected[i].version);
        }

        free(selected);


        for (i = 0;
             i < qSize;
             ++i) {

            free(queue[i].name);

            setFree(
                    &queue[i]
                            .activeExclusions
            );
        }

        free(queue);
    }

    free(directLine);
    free(ruleLine);

    return 0;
}

九、C++算法源码

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <unordered_map>
#include <unordered_set>

using namespace std;

struct Edge {
    string child;
    string version;
    unordered_set<string> exclusions;
};

struct Node {
    string name;

    // 当前依赖路径中累计生效的排除组件
    unordered_set<string> activeExclusions;
};


/**
 * 手动切分字符串,并且保留末尾空字符串。
 *
 * 例如:
 * a:v1:
 *
 * 应得到:
 * a
 * v1
 * ""
 */
vector<string> splitKeepEmpty(
        const string& s,
        char delimiter) {

    vector<string> result;
    string current;

    for (char c : s) {
        if (c == delimiter) {
            result.push_back(current);
            current.clear();
        } else {
            current += c;
        }
    }

    result.push_back(current);

    return result;
}


unordered_set<string> parseExclusions(
        const string& text) {

    unordered_set<string> result;

    if (text.empty()) {
        return result;
    }

    vector<string> names =
            splitKeepEmpty(text, ',');

    for (const string& name : names) {
        result.insert(name);
    }

    return result;
}


int main() {

    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string directLine;
    string ruleLine;

    getline(cin, directLine);

    if (!getline(cin, ruleLine)) {
        ruleLine = "";
    }

    /*
     * 邻接表。
     *
     * vector 保证一个父组件的多个依赖
     * 严格按照输入顺序保存。
     */
    unordered_map<string, vector<Edge>> rules;

    if (!ruleLine.empty()) {

        stringstream ss(ruleLine);

        string item;

        while (ss >> item) {

            vector<string> parts =
                    splitKeepEmpty(item, ':');

            string parent = parts[0];
            string child = parts[1];
            string version = parts[2];

            string exclusionText =
                    parts.size() > 3
                    ? parts[3]
                    : "";

            rules[parent].push_back({
                    child,
                    version,
                    parseExclusions(exclusionText)
            });
        }
    }

    /*
     * unordered_map 用于 O(1) 判断组件是否已经出现。
     *
     * 因为 unordered_map 本身没有输出顺序,
     * 所以另外使用 order 保存第一次出现顺序。
     */
    unordered_map<string, string> selected;

    vector<pair<string, string>> order;

    queue<Node> q;

    if (!directLine.empty()) {

        stringstream ss(directLine);

        string item;

        while (ss >> item) {

            vector<string> parts =
                    splitKeepEmpty(item, ':');

            string name = parts[0];
            string version = parts[1];

            string exclusionText =
                    parts.size() > 2
                    ? parts[2]
                    : "";

            if (!selected.count(name)) {

                selected[name] = version;

                order.push_back({
                        name,
                        version
                });

                q.push({
                        name,
                        parseExclusions(exclusionText)
                });
            }
        }
    }

    /*
     * BFS 保证先处理依赖树上层组件,
     * 再处理下一层。
     */
    while (!q.empty()) {

        Node parent =
                std::move(q.front());

        q.pop();

        auto it = rules.find(parent.name);

        if (it == rules.end()) {
            continue;
        }

        for (const Edge& edge : it->second) {

            /*
             * 如果当前路径已经排除 child,
             * 则 child 以及它的子树全部跳过。
             */
            if (parent.activeExclusions.count(
                    edge.child)) {

                continue;
            }

            /*
             * 第一次出现决定最终位置和版本。
             */
            if (selected.count(edge.child)) {
                continue;
            }

            selected[edge.child] =
                    edge.version;

            order.push_back({
                    edge.child,
                    edge.version
            });

            /*
             * 将父节点排除项复制下来,
             * 再加入当前依赖边新增的排除项。
             */
            auto childExclusions =
                    parent.activeExclusions;

            childExclusions.insert(
                    edge.exclusions.begin(),
                    edge.exclusions.end()
            );

            q.push({
                    edge.child,
                    std::move(childExclusions)
            });
        }
    }

    for (size_t i = 0;
         i < order.size();
         ++i) {

        if (i > 0) {
            cout << ' ';
        }

        cout << order[i].first
             << ':'
             << order[i].second;
    }

    cout << '\n';

    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 新系统 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值