牛客多校第五场 B Graph

Graph

https://ac.nowcoder.com/acm/contest/5670/B

题意:

给你一颗树,给出边权,可以任意加边删边,要求时刻满足树联通, 且每个环的边权异或和为0, 求最后的最小边权

题解:

前置题目: cf 888G 姿势点: Boruvka 字典树

根据bxzy的题解得: 任意两点间的边权是固定的。因为图始终联通,那么所有点之间都至少有一条边,当通过加边使得超过一条边后,环的异或值为0,所以删掉原边后,剩下的边和原边等价,所以两点间边权固定

通过dfs为每个点分配权值,使得两点间异或值等与边权,就成了cf 888G的题目了,也就是最小异或生成树

完整代码

struct Node {
    int v, nex;
    ll w;
} node[Ma * 2];

int head[Ma], cnt;

void init() {
    memset(head, -1, sizeof head);
    cnt = 0;
}

void add(int u, int v, ll w) {
    node[cnt].v = v, node[cnt].w = w;
    node[cnt].nex = head[u], head[u] = cnt++;
}

const int base = 29;

struct Trie {
    int tr[Ma * base][2];
    vector<int> e[Ma * base]; int tot;
    void insert(int x) {
        int u = 0;
        for (int i = base; i >= 0; i--) {
            int t = (x >> i) & 1;
            if (!tr[u][t]) tr[u][t] = ++tot;
            u = tr[u][t];
            e[u].ep(x);
        }
    }
    int ask(int id, int d, int x) {
        if (d < 0) return 0;
        int t = (x >> d) & 1;
        if (tr[id][t]) return ask(tr[id][t], d - 1, x);
        return ask(tr[id][t ^ 1], d - 1, x) + (1 << d);
    }
    ll solve(int id, int d) {
        int l = tr[id][0], r = tr[id][1];
        ll ans = 0;
        if (l and r) {
            if (e[l].size() > e[r].size()) swap(l, r);
            int mi = numeric_limits<int>::max();
            for (size_t i = 0; i < e[l].size(); ++i)
                cmin(mi, ask(r, d - 1, e[l][i]));
            ans += mi + (1 << d);
        }
        if (l) ans += solve(l, d - 1);
        if (r) ans += solve(r, d - 1);
        return ans;
    }
} tri;

int col[Ma];

void dfs(int u, int fa) {
    qxx(i, u) if (node[i].v != fa) {
        col[node[i].v] = col[u] ^ node[i].w;
        dfs(node[i].v, u);
    }
}

signed main() {
    #if SYNC==0
    ios::sync_with_stdio(false);
    cin.tie(0);
    #endif
    init();
    int n; cin >> n;
    rep (i, n - 1) {
        int u, v; ll w; cin >> u >> v >> w;
        add(u, v, w);
        add(v, u, w);
    }
    dfs(0, 0);
    for (int i = 0; i < n; i++)
        tri.insert(col[i]);
    cout << tri.solve(0, base) << endl;

    return 0;
}
全部评论

相关推荐

评论
2
收藏
分享

创作者周榜

更多
正在热议
更多
# 春招至今,你的战绩如何? #
4734次浏览 44人参与
# 你的实习产出是真实的还是包装的? #
1062次浏览 27人参与
# 巨人网络春招 #
11132次浏览 221人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
6891次浏览 36人参与
# 简历第一个项目做什么 #
31243次浏览 312人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
186328次浏览 1114人参与
# 米连集团26产品管培生项目 #
3952次浏览 183人参与
# 面试紧张时你会有什么表现? #
30317次浏览 188人参与
# 简历中的项目经历要怎么写? #
309349次浏览 4149人参与
# 网易游戏笔试 #
6302次浏览 83人参与
# 职能管理面试记录 #
10676次浏览 59人参与
# 把自己当AI,现在最消耗你token的问题是什么? #
6843次浏览 154人参与
# 从哪些方向判断这个offer值不值得去? #
56694次浏览 357人参与
# 腾讯音乐求职进展汇总 #
160388次浏览 1105人参与
# 小红书求职进展汇总 #
226838次浏览 1356人参与
# AI时代,哪些岗位最容易被淘汰 #
62336次浏览 725人参与
# 你怎么看待AI面试 #
179242次浏览 1162人参与
# 正在春招的你,也参与了去年秋招吗? #
362478次浏览 2631人参与
# 你的房租占工资的比例是多少? #
92120次浏览 896人参与
# 机械求职避坑tips #
94393次浏览 567人参与
# 校招笔试 #
466042次浏览 2950人参与
# 面试官最爱问的 AI 问题是...... #
27052次浏览 834人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务