zoukankan      html  css  js  c++  java
  • 【每日一题】21.边的染色 (DFS连通图 + 思维)

    补题链接:Here

    思维不够,看到这种陌生的题目无从下手.

    这题应该做过一次的人会觉得它其实并不难.
    主要思想:把边权->点权.
    这样做的好处是,无论你怎么分配点权,在环内的异或值一定为 (0) (前提是环内的一定合法.)
    做题步骤也是围绕这些性质来的.

    1. 首先判断给定的点是否有矛盾,就是你给一个点赋值,它假如是环的话,有矛盾,那么它的异或值为 (1) .然后你这个点的异或值会和你之前给定它的异或值不同.
    2. 找有多少联通块,不同的联通块是独立事件,用乘法原理.然后点权的设置,其实本身存在重复,就是你把所有点取反和不取反,这两种情况的边权是一样的.然后本身没有限制,假设联通块大小是 (k) 那么就是(2^k) .去除重复就是 (2^{k - 1})
    3. 考虑限制,一旦给一段连续的限制,你给头部元素赋值 (1/0) ,它这一段都是确定的,换句话来说,它这一段的贡献只有(2) 所以我们应该把之前多算的贡献消掉,假如这段联通块大小是 (p) ,那么我们必须把 (ans/=2^{p-1})
    using ll      = long long;
    const int mod = 998244353;
    const int N   = 1e5 + 10;
    vector<pair<int, int>> e[N]; // u,v,w
    int color[N];
    bool vis[N];
    bool dfs0(int u, int col) {
        color[u] = col;
        for (auto v : e[u]) {
            if (v.second == -1) continue;
            if (color[v.first] != -1 and col ^ v.second != color[v.first]) return false;
            if (color[v.first] == -1 and !dfs0(v.first, col ^ v.second)) return false;
        }
        return true;
    }
    int dfs(int u, bool f) {
        int ans = 1;
        vis[u]  = true;
        for (auto v : e[u]) {
            if (f and v.second == -1) continue;
            if (!vis[v.first]) ans += dfs(v.first, f);
        }
        return ans;
    }
    void solve() {
        int n, m;
        cin >> n >> m;
        while (m--) {
            int u, v, w;
            cin >> u >> v >> w;
            e[u].push_back({v, w});
            e[v].push_back({u, w});
        }
        memset(color, -1, sizeof(color));
        for (int i = 1; i <= n; ++i)
            if (color[i] == -1) {
                if (!dfs0(i, 1)) {
                    cout << "0
    ";
                    return;
                }
            }
        int k = 0;
        for (int i = 1; i <= n; ++i)
            if (!vis[i]) k += dfs(i, false) - 1;
        memset(vis, false, sizeof vis);
        for (int i = 1; i <= n; ++i)
            if (!vis[i]) k -= dfs(i, true) - 1;
        int ans = 1;
        for (int i = 1; i <= k; ++i)
            ans *= 2, ans %= mod;
        cout << ans << '
    ';
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    jdbc概述
    MongoDB(三):数据库操作、集合操作
    MongoDB(二):在Windows环境安装MongoDB
    MongoDB(一):NoSQL简介、MongoDB简介
    python基础(36):pymysql模块
    Web前端基础(19):jQuery基础(六)
    Web前端基础(18):jQuery基础(五)
    Web前端基础(17):jQuery基础(四)
    Web前端基础(16):jQuery基础(三)
    Web前端基础(15):jQuery基础(二)
  • 原文地址:https://www.cnblogs.com/RioTian/p/14744165.html
Copyright © 2011-2022 走看看