• 【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;
    }
  • 相关阅读:
    vs2005设置断点不能调试问题(方法三为首选项,一般都可以解决)
    SQL中内连接和外连接的问题!
    javascript读写删cookie的简单方法
    数据库语句 select * from table where 1=1 的用法和作用
    gridview 和repeater 添加序号的方法
    asp.net Forms身份验证详解(转载)
    Asp.net中的认证与授权(转载)
    ASP.NET中前台javascript与后台代码调用
    android 模拟器不能上网解决方法
    大数据量系统架构
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/8849380.html
Copyright © 2020-2023  润新知