zoukankan      html  css  js  c++  java
  • 给定一个无向简单图(即无重边无自环),每条边都有一个权值。

    这个图的一个割,指的是将它的点集划分为两个不重不漏的集合 (S)(T)

    这个割的权值,是所有两个端点分别属于 (S)(T) 的边的权值的异或和(即 (S) 内部的边和 (T) 内部的边都不算)。

    现在问这个图的 割的所有可能的权值 的和是多少。

    由于这个数很大,只需要输出 (9) 位,不足 (9) 位则全部输出。

    输入格式

    第一行两个数 (n)(m) 表示图的点数和边数。
    之后 (m) 行每行 (3) 个数 (x, y, z) 表示一条边的两个端点和这条边的权值。点的编号从 (1)(n)

    输出格式

    一行一个整数表示答案。

    数据范围

    (1le nle 10^5,1le mle min(frac{n(n-1)}{2},2 imes 10^5),0le zle 10^9)


    考场上看成对所有划分数求和了,那个真是没法做...

    考虑所有点都是白色,然后选择一个点染黑,会选择与这个点相连的所有边

    选择任意个不相邻的点染黑,会选择与这些点相连的边

    选择一对相邻的点染黑,那么某条边就不会被选了,可以被刚好异或掉

    因此,设定点权为与它相连的边权的异或和,对点求线性基就可以了

    然后在最后统计答案的时,所有满秩的位置显然可以选 0/1 ,那么其余满秩位置随便选的。

    但是不满秩的位置可能是 0 或者 1,我们一样需要统计非满秩位置的 1,不过当你选择这个非满秩的 1 时,实际上也钦定了某个满秩的位置是 1,所以一样的统计就可以了


    Code:

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using std::min;
    const int SIZE=1<<21;
    char ibuf[SIZE],*iS,*iT;
    //#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
    #define gc() getchar()
    template <class T>
    void read(T &x)
    {
        x=0;int f=0;char c=gc();
        while(!isdigit(c)) f|=c=='-',c=gc();
        while(isdigit(c)) x=x*10+c-'0',c=gc();
        if(f) x=-x;
    }
    const int N=1e5+10;
    int n,m,yuu[N],aya[30],cnt,base[40];
    ll ans;
    void ins(int x)
    {
        for(int i=30;~i;i--)
            if(x>>i&1)
            {
                if(base[i]) x^=base[i];
                else
                {
                    base[i]=x;
                    return;
                }
            }
    }
    int main()
    {
        read(n),read(m);
        for(int u,v,z,i=1;i<=m;i++)
        {
            read(u),read(v),read(z);
            yuu[u]^=z,yuu[v]^=z;
        }
        for(int i=1;i<=n;i++) ins(yuu[i]);
        for(int i=0;i<=30;i++) cnt+=base[i]>0;
        for(int i=0;i<=30;i++)
        {
            int flag=0;
            for(int j=0;j<30;j++) flag|=base[j]>>i&1;
            if(flag)
                ans+=(1ll<<cnt-1)*(1ll<<i);
        }
        while(ans) aya[++aya[0]]=ans%10,ans/=10;
        for(int i=1;i<=min(aya[0],9);i++)
            printf("%d",aya[aya[0]-i+1]);
        return 0;
    }
    

    2019.6.14

  • 相关阅读:
    BZOJ2005 能量汇集 【gcd求和】
    莫比乌斯反演
    匈牙利算法 求二分图最大匹配
    HDU3507 print article【斜率优化dp】
    tyvj1305 最大子序和 【单调队列优化dp】
    NOIP2017 列队 题解报告【56行线段树】
    NOIP2017 宝藏 题解报告【状压dp】
    NOIP2017 逛公园 题解报告 【最短路 + 拓扑序 + dp】
    好的软件测试人员简历是什么样子的?
    淘宝网-接口测试白皮书V0.1
  • 原文地址:https://www.cnblogs.com/butterflydew/p/11022082.html
Copyright © 2011-2022 走看看