#小红的基环树染色构造#

F-小红的基环树染色构造_牛客周赛 Round 126

该问题要求在一个基环树(Unicyclic Graph)上进行3-染色(3-Coloring)。基环树的拓扑结构可以严格定义为:一个核心环(Cycle)+ 若干挂在环上节点的树(Trees)。

  • 核心约束:任意相邻节点颜色不同。
  • 可用资源:3种颜色(红、黄、蓝)。
  • 解的存在性:题目保证必然存在解。根据图论原理,任何简单图只要不是完全图 及其特例,并且最大度数与色数满足一定关系,通常容易染色。对于基环树:
    • 树部分:这是二分图,仅需2种颜色即可完成染色。
    • 环部分:偶环需要2色,奇环需要3色。
    • 结论:由于提供了3种颜色,即使环是奇数长度,也能完美覆盖。

拓扑分解与分步处理

解决基环树问题的最优架构通常采用环树分离策略。我们不应将图视为一个整体进行复杂的搜索,而应将其分解为两个独立的子问题:

  1. 环的处理:解决闭环结构的冲突。
  2. 树的处理:解决层级结构的传播。

算法

DFS 找环 + 贪心染色 + 树的遍历

相比于拓扑排序(剥洋葱法),直接使用 DFS(深度优先搜索) 处理此问题更为直观且易于实现状态的传递。

  1. 第一阶段(寻环):通过 DFS 找到图中的那条“回边(Back Edge)”,从而锁定环上的所有节点。
  2. 第二阶段(环染色):优先对环上的节点进行染色。由于环上的节点同时受前后两个邻居限制,属于“高约束”区域,必须优先满足。
  3. 第三阶段(树染色):以环上的节点为“根”,向外延伸的树进行染色。这部分约束极低(只受父节点限制),可直接贪心。

代码实现

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve() {
    int n;
    cin >> n;
    vector<vector<int>> g(n + 1);
    for (int i = 0; i < n; i++) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    // 0: 未访问, 1: 访问中(在栈里), 2: 已完全访问
    vector<int> vis(n + 1, 0);
    vector<int> parent(n + 1, -1);
    vector<int> cycle;
    vector<bool> onCycle(n + 1, false);
    bool found = false;
    auto dfs_cycle = [&](auto&& self, int u, int p) -> void {
        vis[u] = 1;
        parent[u] = p;

        for (int v : g[u]) {
            if (v == p)
                continue;
            if (vis[v] == 1) {
                if (!found) {
                    found = true;
                    int cur = u;
                    while (cur != v) {
                        cycle.push_back(cur);
                        onCycle[cur] = true;
                        cur = parent[cur];
                    }
                    cycle.push_back(v);
                    onCycle[v] = true;
                }
            } else if (vis[v] == 0) {
                self(self, v, u);
            }
        }

        vis[u] = 2;
    };
    dfs_cycle(dfs_cycle, 1, -1);

    vector<int> color(n + 1, 0);
    int m = cycle.size();
    for (int i = 0; i < m; i++) {
        if (i % 2 == 0) {
            if (m % 2 == 1 && i == m - 1)
                color[cycle[i]] = 3;
            else
                color[cycle[i]] = 1;
        } else if (i % 2 == 1) {
            color[cycle[i]] = 2;
        }
    }

    auto dfs_color = [&](auto&& self, int u, int p) -> void {
        for (int v : g[u]) {
            if (v == p || onCycle[v])
                continue;
            if (color[u] == 1)
                color[v] = 2;
            else
                color[v] = 1;
            self(self, v, u);
        }
    };
    for (int i = 1; i <= n; i++) {
        if (onCycle[i])
            dfs_color(dfs_color, i, -1);
    }

    for (int i = 1; i <= n; i++) {
        cout << color[i] << " ";
    }
    cout << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;

    while (T--) {
        solve();
    }

    return 0;
}
#牛客十周岁生日快乐#
算法编程训练 文章被收录于专栏

各类牛客算法编程训练联赛、集训营

全部评论

相关推荐

01-14 02:10
已编辑
门头沟学院 Java
十月底没收到转正意向&nbsp;离职秋招&nbsp;完美错过金九银十窗口期&nbsp;差点以为要失业了算法还不错(面试手撕遇见过很多非hot100&nbsp;仅失手一次)基础知识还算挺ok&nbsp;实习是大厂时间挺长但工作简单也没包装(多次被点评诚实)最终还是有工打&nbsp;也顺利逃离北京了字节:部门1&nbsp;hr面结束泡很久很久-感谢信,部门2三面拒阿里:某俩bu&nbsp;oc,☁️二面挂,国际&nbsp;钉钉约面拒🐧:&nbsp;约面0次(maybe投太晚了maybe太菜了)🐜:三面后感谢信美团:一面挂(12月初&nbsp;问的问题不算简单都答上了&nbsp;反手一道非hot100&nbsp;hard,&nbsp;没辙)👋:&nbsp;oc&nbsp;拒京东:offer待撕(谢谢东哥&nbsp;最早给我发offer的)百度:约面拒🍊:oc&nbsp;拒🦐:部门2oc拒&nbsp;部门1二面挂(有点莫名其妙)🐬:oc&nbsp;拒🍠:部门1一面过不推进(部门2面试官问我为什么上次一面过了不推进&nbsp;我也懵&nbsp;你以为我不想推进?)&nbsp;部门2一面过不推进(hr真是好心人&nbsp;告诉我通过但是不推进&nbsp;不如直接告诉我没过)其他:(base南方&nbsp;听起来还行的公司投了一些)微众银行&nbsp;商汤&nbsp;顺丰&nbsp;某ai创业公司&nbsp;oc拒,东方财富二面后hr已读不回,同程一面无后续&nbsp;小鹏二面挂(想给差评的一家)&nbsp;某自驾公司二面挂&nbsp;,爱奇艺约面拒10月底到12月中旬面试都推进很慢很拷打心态(表扬一下🐜面试完立即推送通过否&nbsp;虽然通过也不一定约下一轮)&nbsp;很多次hr面后无限泡&nbsp;感觉自己进步了很多but没什么眉目&nbsp;多度焦虑以为只有东哥要我了!12月底很多公司飞速推进&nbsp;陆续收到了一些offer(谢谢大佬们释放)(8月有佛系裸面两家大厂&nbsp;误以为秋招易如反掌,十月底离职后真切感受&nbsp;地狱才是晚投的真相!27届看见这贴的!!早准备!!早投!!不要all&nbsp;in实习!!不要跟我一样太懒太佛太乐观!!)在经历极致焦虑后&nbsp;最坏的情况并未发生&nbsp;自己仍有选择和出路,秋招最大的收获&nbsp;就是意识到天没那么容易塌!拥抱自己的局限性&nbsp;也认识自己的能动性!!and&nbsp;希望新工作可以多苟一阵&nbsp;好讨厌找工作!
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务