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

  • 相关阅读:
    OpenGLES 怎样在十天内掌握线性代数
    Matlab自己定义函数
    小小小女神啊~~~
    Format类及其子类功能和使用方法具体解释
    数据库集群
    分布式SESSION
    二级缓存
    应用服务器集群部署
    业务拆分和分级
    最简中间件集群方案
  • 原文地址:https://www.cnblogs.com/butterflydew/p/11022082.html
Copyright © 2011-2022 走看看