• 【题解】割cut [牛客Wannafly挑战赛1 E]


    【题解】割cut [牛客Wannafly挑战赛1 E]

    传送门:( ext{cut}) [牛客 ( ext{Wannafly}) 挑战赛 ( ext{1 E})]

    【题目描述】

    给定一个 (n) 个点 (m) 条边的无向简单图(无重边无自环),每条边都有权值 (w) 。图的一个割指:将点集划分为两个不重不漏的集合 (S)(T) 。割的权值为所有两个端点分别属于 (S)(T) 的边的权值异或和(即 (S) 内部的边和 (T) 内部的边不算)。

    现求这个图的割的所有可能的权值之和,输出答案前 (9) 位(不足 (9) 位则全部输出)。

    【输入输出样例】

    样例输入:
    2 1
    1 2 1
    
    样例输出:
    1
    

    【数据范围】

    对于 (20 \%:) (nleqslant 20,) (mleqslant 400)

    另外 (20 \%:) (m=n-1,) 保证读入的图是一棵树。

    另外 (20 \%:) (wleqslant 16)

    对于 (100 \%:) (1leqslant nleqslant 10^5,) (1leqslant mleqslant min(frac{n(n-1)}{2},2 imes10^5),) (0leqslant wleqslant 10^9)

    【分析】

    这题被放到了今天 ( ext{NOI}) 模拟赛 ( ext{day2 T2})

    样例差评 样例差评 样例差评 样例差评 样例差评

    题目描述差评 题目描述差评 题目描述差评 题目描述差评 题目描述差评

    题目要求的是割所有可能的权值之和不是所有割的权值之和!

    一开始题目理解错误,头都快想炸了还是没有思路,只差没破口大骂了。

    对于 (nleqslant 20) 的部分直接 (2^n) 枚举割的划分方式,然后枚举所有边求权值。复杂度 (2^nmapprox O(4 imes 10^8)),显然会超时(实际效率不清楚,或许常数小能卡过?),考虑把枚举边改为枚举两个点集,于是降为 (sum_{i=1}^{n}C_{n}^{i}i(n-i)approx n^22^{n-2}approx O(10^8))

    对于一棵树的情况,发现任意选出一些边砍掉都可以划分成割(因为一定能划成二分图),于是题意变为:给出 (m) 个值,求任选一些值可能的异或和之和。

    显然要挂一个线性基。但问题在于如何快速求所有异或和之和,(O(2^{size})) 暴力枚举显然是不行的,考虑按位处理:对于每一位 (i),若存在某个基的第 (i) 位为 (1),那么答案加上 (2^i2^{size-1})

    正确性证明:
    任选一个第 (i) 位为 (1) 的基 (p) 把它去掉,在剩下的 (size-1) 个基中进行选择,易知有 (2^{size-1}) 种不同的异或和,设异或和第 (i) 位为 (0) 的有 (cnt_0) 种,为 (1) 的有 (cnt_1) 种(显然 (cnt_0+cnt_1=2^{size-1}))。现在把它们都异或上 (p),则又得到 (cnt_0) 种第 (i) 位为 (1) 的,(cnt_1) 种第 (i) 位为 (0) 的。故第 (i) 位为 (1) 的共有 (cnt_0+cnt_1=2^{size-1}) 种。

    对于一般的无向简单图,考虑将每个点所连的边权值都异或起来,并作为这个点的点权,那么点集 (S)(或者 (T))的点权异或和就是割的权。

    正确性证明:
    若边的两个端点在不同点集,那么该边权只会被异或一次,反之会被异或两次消掉(即变为 (0)) 。

    于是问题转换为:任选一些点作为点集 (S),计算其可能的点权异或和之和。

    发现和上面那个问题一模一样,只是插入线性基的值不同了。

    还剩下最后一个问题:怎么输出前 (9) 位?

    总不可能现场写一个高精吧.....于是我去问了问教练,发现 ( ext{std}) 直接开 ( ext{ull}) 就过了,珂啪。

    时间复杂度为:(O(m+log^{2}inf))

    (wleqslant 16) 的部分分是给那些只会 (O(2^{size})) 枚举线性基统计答案的人准备的)

    【Code】

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define LL unsigned long long
    #define Re register int
    using namespace std;
    const int N=1e5+3,M=2e6+3;
    int n,m,x,y,z,o=1,head[N];LL ans;
    struct QAQ{int w,to,next;}a[M<<1];
    inline void add(Re x,Re y,Re z){a[++o].w=z,a[o].to=y,a[o].next=head[x],head[x]=o;}
    inline void in(Re &x){
        int f=0;x=0;char ch=getchar();
        while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
        while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
    }
    struct JI{
        int cnt,p[33];
        inline void insert(Re x){
            for(Re i=30;i>=0;--i)
                if((x>>i)&1){
                    if(!p[i]){++cnt,p[i]=x;break;}
                    x^=p[i];
                }
        }
    }ji;
    int cnt;
    inline void print(LL x){
        if(x>9)print(x/10);
        putchar(x%10+'0');
        if(++cnt>=9)exit(0);
    }
    int main(){
    //    freopen("cut.in","r",stdin);
    //    freopen("cut.out","w",stdout);
        in(n),in(m);
        for(Re i=1;i<=m;++i)in(x),in(y),in(z),add(x,y,z),add(y,x,z);
        for(Re x=1;x<=n;++x){
            Re v=0;
            for(Re i=head[x];i;i=a[i].next)v^=a[i].w;
            ji.insert(v);
        }
        for(Re i=0;i<=30;++i){
            Re flag=0;
            for(Re j=0;j<=30;++j)if(ji.p[j])flag|=((ji.p[j]>>i)&1);
            if(flag)ans+=(LL)(1<<i)*(1<<(ji.cnt-1));
        }
        print(ans);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
  • 相关阅读:
    异步IO数据库队列缓存
    requests.post发送字典套字典
    Git
    Django REST framework
    7. 函数-自定义函数
    6. 小数据池-编码-文件操作
    5. 基本数据结构-集合
    4. 基本数据结构-字典
    3. 基本数据结构-元组
    2. 基本数据结构-列表
  • 原文地址:https://www.cnblogs.com/Xing-Ling/p/13490244.html
Copyright © 2020-2023  润新知