zoukankan      html  css  js  c++  java
  • 【BFS】【最小生成树】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem G. We Need More Managers!

    题意:给你n个点,点带权,任意两点之间的边权是它们的点权的异或值中“1”的个数,问你该图的最小生成树。

    看似是个完全图,实际上有很多边是废的。类似……卡诺图的思想?从读入的点出发BFS,每次只到改变它的任意一位所能到达的点(不论是否读入)。

    记录每个点是从哪个读入点BFS过来的,当第二次访问某个点的时候,就将它的两个源头(一次是第一次的时候标记的,一次是第二次过来的)连一条边。

    这样最多连m(位数)*n条边,实际上比这个值更小。

    这种做法可以将很多显然不会出现在最小生成树里的边排除掉。

    opencup的标程:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    // O(kn)
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    struct FAU {
        vector <int> p, r;
    
        FAU(int n): p(n,-1), r(n,0) {}
    
        int find(int x) {
            if (p[x] == -1) return x;
            return p[x] = find(p[x]);
        }
    
        void join(int x, int y) {
            x = find(x); y = find(y);
            if (x == y) return ;
    
            if (r[x] > r[y]) p[y] = x;
            else p[x] = y;
    
            if (r[x] == r[y]) ++r[y];
        }
    };
    
    int readBinary() {
        string s;
        cin >> s;
        
        int result = 0;
        for (char c : s) {
            result = 2 * result + ((c == 'L') ? 1 : 0);
        }
        
        return result;
    }
    
    void solveTestcase() {
        int k, n;
        cin >> k >> n;
    
        const int N = 1 << k;
        
        vector <int> dist(N, -1), from(N);
        queue <int> q;
        
        for (int i = 0; i < n; i++) {
            int val = readBinary();
            
            dist[val] = 0;
            from[val] = i;
            
            q.push(val);
        }
        
        vector <vector <pair<int,int>>> edges(k+1);
        
        while (!q.empty()) {
            int v = q.front(); q.pop();
            
            for (int bit = 0; bit < k; bit++) {
                int u = v ^ (1 << bit);
                
                if (dist[u] == -1) {
                    dist[u] = 1 + dist[v];
                    from[u] = from[v];
                    
                    q.push(u);
                } else if (from[u] != from[v]) {
                    int len = dist[u] + dist[v] + 1;
                    
                    if (len <= k) {
                        edges[len].push_back({from[u], from[v]});
                    }
                }
            }
        }
        
        FAU fau(n);
        int ans = 0;
        
        for (int len = 1; len <= k; len++) for (auto &edge : edges[len]) {
            if (fau.find(edge.first) != fau.find(edge.second)) {
                ans += len;
                fau.join(edge.first, edge.second);
            }
        }
        
        cout << ans << '
    ';
    }
    
    int main() {
        ios_base::sync_with_stdio(false);
        
        int z;
        cin >> z;
        
        while (z--) {
            solveTestcase();
        }
        
        return 0;
    }
  • 相关阅读:
    Linq 入门 顺带 Func与Action
    关于asp.net 的一些好资料地址 , 防止丢失!
    Sql日期时间格式转换 备用
    自己动手写 ASP.NET MVC 分页 part1
    怎么做好一个美食排行榜的用户投票功能?
    「要买车网」免费获取汽车电商要买车网购车优惠券
    MVC Ajax Form & Ajax Valida(笔记)
    C# 序列化高级用法
    我与葡萄城的故事
    生成分布式随机ID
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/8849380.html
Copyright © 2011-2022 走看看