• 线性基


    整理一下线性基的题

    HDU 5544

    题意

    给一个有边权的无向图,找一条闭合路径,使路径上权值异或和最大

    题解

    Hint1 如果这个图是一棵树?

    Hint2 环之间相互独立?

    对图进行一遍DFS,把所有找到的环插入线性基,再求最大值即可

    #include <iostream>
    #include <vector>
    using namespace std;
    #define N 500010
    typedef long long LL;
    vector< pair<int, LL> > G[N];
    int T, n, m, u, v, cas, vis[N];
    LL xorsum[N], p[N], w;
    
    void insert(LL x) {
        for (int i = 62; i >= 0; i --) if ((x >> i) & 1) {
            if ( p[i] ) {
                x ^= p[i];
            } else {
                p[i] = x; 
                break;
            }
        }
    }
    
    void dfs(int u) 
    {
        vis[u] = 1;
        for (int i=0;i<G[u].size();i++) 
        {   
            int v = G[u][i].first;
            if (vis[v] == 1) {
                insert(xorsum[u] ^ G[u][i].second ^ xorsum[v]);
            } else {
                xorsum[v] = xorsum[u] ^ G[u][i].second;
                dfs(v);
            }
        }
    }
    
    int main() {
        scanf("%d", &T);
        while (T --) {
            scanf("%d %d", &n, &m);
    
            for (int i = 0; i <= n; i ++) 
                G[i].clear(), xorsum[i] = 0, vis[i] = 0;
            
            for (int i = 0; i <= 62; i ++)
                p[i] = 0;
    
            for (int i = 1; i <= m; i ++) {
                scanf("%d %d %lld", &u, &v, &w);
                G[u].push_back(make_pair(v, w));
                G[v].push_back(make_pair(u, w));
            }
    
            dfs(1);
    
            LL ans = 0; 
            for (int i = 62; i >= 0; i --) if ((p[i] ^ ans) > ans) 
                ans ^= p[i];
    
            printf("Case #%d: %lld
    ", ++ cas, ans); 
        }
    }
    
    

    WannaFly 挑战赛1 E

    题意

    给定一个无向简单图(即无重边无自环). 每条边都有一个权值. 这个图的一个鸽, 指的是将它的点集划分为两个不重不漏的集合S和T. 这个鸽的权值, 是所有两个端点分别属于S和T的边的权值的异或和(即, S内部的边和T内部的边都不算). 现在问这个图的鸽的所有可能权值的和是多少. 由于这个数很大, 只需要输出前9位, 不足9位则全部输出.

    题解

    每个划分方式对应一个二分图。辣么我们枚举所有的二分图。
    把每个点的点权设为:与该点先连的边的权值异或和。然后把这些点权插入线性基即可。
    考虑每个点取还是不取的同时,二分图就被枚举了。

    #include <iostream>
    using namespace std;
    typedef long long LL;
    #define N 5000000
    int n, m, u, v;
    LL w, a[N], p[N];
    void ins(LL x) {
        for (int i = 40; i >= 0; i --) if ((x >> i) & 1){
            if (!p[i]) {
                p[i] = x; break;
            } else {
                x ^= p[i];
            }
        }
    }
    int main() {   
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; i ++) {
            scanf("%d %d %lld", &u, &v, &w);
            a[u] ^= w; a[v] ^= w;
        }
        for (int i = 1; i <= n; i ++) {
            ins(a[i]);
        }
        LL ans = 0, cnt = 0;
        for (int i = 0; i <= 40; i ++) if (p[i]) cnt ++;
    
        for (int i = 0; i <= 40; i ++) 
            for (int j = 0; j <= i-1; j ++) 
                p[i] ^= (p[i] & p[j]);
    
        for (int i = 0; i <= 40; i ++) {
            ans = ans + p[i] * (1LL << (cnt - 1));
        }
        while (ans >= 1000000000) ans /= 10;
        printf("%lld
    ", ans);
    }
    
    

    高斯消元版本

    #include <iostream>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const int N = 100000+10;
    int n, m, a[N], u, v, w;//0-index
    int bit[32];
    
    int main() {
         
        scanf("%d %d", &n, &m);
        for (int i=1;i<=m;i++) {
            scanf("%d %d %d", &u, &v, &w);
            a[--u] ^= w, a[--v] ^= w;
        }
         
     
        int q = 0;
        for (int j = 31; j >= 0; j --)
            for (int i = q; i < n; i ++)
                if ((a[i] >> j) & 1) {
                    swap(a[i], a[q]);
                    bit[q ++] = (1 << j);
                    for (int k = q; k < n; k ++) {
                        if (a[k] & bit[q-1])
                            a[k] ^= a[q-1];
                    }
                }
         
     
        for (int i = q-1; i >= 0; i --)
            for (int j = i-1; j >= 0; j --)
                a[j] ^= (a[j]&a[i]);
         
     
        LL ans = 0;
        for (int i = 0; i < q; ++i)
        {
            ans += (1LL << (q - 1)) * a[i];   
        }
        while (ans > 999999999) {
            ans /= 10;
        }
        printf("%lld
    ", ans);
    }
    

    TopCoder - 12197

    高斯消元后贪心凑最大。注意到:若两向量组张成的空间相同,则为等价。

    LL maxSum(vector<LL> a) {
            n = a.size();
            int q = 0; 
            for (int j=60;j>=0;j--)
                for (int i=q;i<n;i++) 
                    if ((a[i]>>j)&1) {
                        swap(a[i], a[q]);
                        bit[q ++] = (1LL<<j);
                        for (int k=q;k<n;k++)
                            if (a[k]&(1LL<<j)) a[k]^=a[q-1];
                    }  
            for (int i=q-1;i>=0;i--)
                for (int j=i-1;j>=0;j--) 
                    if (a[j] & bit[i]) a[j] ^= a[i];
            
            for (int i=1;i<q;i++) 
                a[0] ^= a[i];
            
            for (int i=1;i<n;i++) 
                a[i] ^= a[0];
            
            LL ans = 0;
            for (int i=0;i<n;i++)
                ans += a[i];
    
            return ans;
        }
    
  • 相关阅读:
    js 字符串indexOf方法封装
    js 冒泡排序
    CSS定位 position的三个属性 elative 、absolute、fixed :
    让父元素能感知浮动的子元素 #用伪元素清除浮动
    三个路由器的连接,中间路由的配置(静态路由)
    IDEA 添加tomcat出错: Error: Environment variable name is not set 我的解决方法
    通过基于AspectJ 注解的方式实现Spring AOP报 can't find referenced pointcut myPointCut 错误,我的解决方法
    C语言fopen函数打开文本文件与二进制文件的区别
    位运算的奇技淫巧 系列1
    位运算例子(以后会逐渐补充)
  • 原文地址:https://www.cnblogs.com/RUSH-D-CAT/p/7675154.html
Copyright © 2020-2023  润新知