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

  • 相关阅读:
    今天没有写的,唱首歌吧。。
    UILocalNotification实现本地的闹钟提醒的方法。
    又是动画效果~
    c位运算符
    javascript如何调用objectivec的方法
    在tableview索引中显示搜索符号的方法
    检查数据库|| 复制数据库文件
    往sqlite中写入图片二进制数据及读取源码 for iphone
    [Cocoa]深入浅出 Cocoa 之消息(罗朝辉)
    关于malloc问题的改错笔试常考
  • 原文地址:https://www.cnblogs.com/butterflydew/p/11022082.html
Copyright © 2011-2022 走看看