• 【BZOJ-2115】Xor 线性基 + DFS


    2115: [Wc2011] Xor

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 2142  Solved: 893
    [Submit][Status][Discuss]

    Description

    Input

    第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目。 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边。 图中可能有重边或自环。

    Output

    仅包含一个整数,表示最大的XOR和(十进制结果),注意输出后加换行回车。

    Sample Input

    5 7
    1 2 2
    1 3 2
    2 4 1
    2 5 1
    4 5 3
    5 3 4
    4 3 2

    Sample Output

    6

    HINT

    Source

    Solution

    线性基

    思路就是先随意一条路径,然后把每个环的存下来,求线性基,再与之前的路径取xor,取最大即为答案

    至于线性基,它的意义是:通过原集合S的某一个最小子集S1使得S1内元素相互异或得到的值域与原集合S相互异或得到的值域相同。

    然后XJB乱搞一下,具体写的比较明白的还是Oxer  折越

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    long long read()
    {
        long long x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define maxn 500010
    #define maxm 5000010
    int n,m,num;
    struct EdgeNode{int next,to;long long val;}edge[maxm<<1];
    int head[maxn],cnt;
    void add(int u,int v,long long w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].val=w;}
    void insert(int u,int v,long long w) {add(u,v,w); add(v,u,w);}
    bool visit[maxn];long long val[maxn],a[maxn];
    void DFS(int now)
    {
        visit[now]=1;
        for (int i=head[now]; i; i=edge[i].next)
            if (!visit[edge[i].to])
                val[edge[i].to]=val[now]^edge[i].val,DFS(edge[i].to);
            else a[++num]=val[edge[i].to]^edge[i].val^val[now];
    }
    int Gauss()
    {
        int tmp=1;
        for (int p=64; p>=0; p--)
            {
                int t=0;
                for (int j=tmp; j<=num; j++) if ((a[j]>>p)&1) {t=j;break;}
                if (t)
                    {
                        swap(a[t],a[tmp]);
                        for (int j=1; j<=num; j++) if (j!=tmp && ((a[j]>>p)&1)) a[j]^=a[tmp];
                        tmp++;
                    }
            }
        return tmp-1;
    }
    int main()
    {
        n=read(); m=read();
        for (int u,v,i=1; i<=m; i++) u=read(),v=read(),insert(u,v,read());
        DFS(1);
        long long ans=val[n];
        num=Gauss();
        for (int i=1; i<=num; i++) ans=max(ans,ans^a[i]);
        printf("%lld
    ",ans);
        return 0;
    }

    hsy大爷发题不写题解,程序还是hzwer的翻版

  • 相关阅读:
    从killchain的角度检测APT攻击
    挖洞实战之信息泄露与前端加密
    浅析MySQL恶意服务器读取文件原理
    MySQL决胜秋招Section
    MySQL窗口函数
    MySQL集合运算
    Chrome 插件神仙网站推荐 !直接就能下,2022年最新!
    Clickhouse分桶聚合后填充零值问题
    深入理解C#笔记
    JavaCV音视频开发宝典:视频转码和转封装有什么区别?使用rtsp拉流转推到rtmp案例来讲一下转码和转封装实现的区别
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5517109.html
Copyright © 2020-2023  润新知