zoukankan      html  css  js  c++  java
  • codeforces 724G

    题目传送门

    题意:给出衣服无向带权图,问有多少对合法的$<u,v,s>$,要求$u$到$v$存在一条路径(不一定是简单路径)权值异或和等于$s$,并且$u<v$。求所有合法三元组的s的和。

    思路:

      参考了一篇大佬的博客。

      这类题的核心思想就是,两点之间的所有可能的路径,都是由一条简单路径加上若干个环组成的。u,v两点所有路径的异或值的集合,等价于,u,v一条简单路径的异或值,与整个连通图的所有环组成的线性基异或的集合。

      所以按位考虑每个二进制1给整幅图带来的价值。

      特别要注意的一点是,在处理线性基的过程中,最多处理到63位,如果处理到64位及以上,当$i>=64$,某些$(x>>i)$,或者$(x<<i)$,就会发出许多诡异的错误,wa了很久。

    #pragma GCC optimize (2)
    #pragma G++ optimize (2)
    #pragma comment(linker, "/STACK:102400000,102400000")
    #include<bits/stdc++.h>
    #include<cstdio>
    #include<vector>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define dep(i,b,a) for(int i=b;i>=a;i--)
    #define clr(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    #define pii pair<int,int >
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    ll rd()
    {
        ll 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;
    }
    const int maxn=100010;
    const ll mod=1e9+7;
    int n,m;
    struct edge{
        int to;
        ll w;
    };
    vector<edge >ve[maxn];
    int vis[maxn];
    ll del[maxn],p[70],siz,num[70],ans=0,tot=0;
    void init(){
        rep(i,1,n){
            ve[i].clear();
            vis[i]=0;
        }
        ans=0,siz=0,clr(p,0);
    }
    bool insert(ll x){
        dep(i,63,0){
            if((x>>i)&1){
                if(!p[i]){
                    p[i]=x;
                    return true;
                }
                x^=p[i];
            }
        }
        return false;
    }
    void dfs(int u,ll res){
        del[u]=res;
        for(ll i=63;i>=0;i--){
            if(((res>>i)&1)){
                num[i]++;
            }
        }
        tot++;
        vis[u]=1;
        for(auto &st:ve[u]){
            if(!vis[st.to]){
                dfs(st.to,res^st.w);
            }else{
                if(insert(res^st.w^del[st.to])){
                    siz++;
                }
            }
        }
    }
    int main(){
        while(cin>>n>>m){
            init();
            rep(i,1,m){
                int u,v;
                ll w;
                u=rd(),v=rd(),w=rd();
                ve[u].pb({v,w});
                ve[v].pb({u,w});
            }
            rep(u,1,n){
                if(!vis[u]){
                    tot=0;
                    clr(p,0),siz=0;
                    clr(num,0);
                    dfs(u,0);
                    dep(i,63,0){
                        bool ok=0;
                        dep(j,63,0){
                            if((p[j]>>i)&1)ok=1;
                        }
                        if(ok){
                            ans=(ans+tot*(tot-1)/2%mod*((1ll<<(siz-1))%mod)%mod*((1ll<<i)%mod)%mod)%mod;
                        }else{
                            ans=(ans+num[i]*(tot-num[i])%mod*((1ll<<siz)%mod)%mod*((1ll<<i)%mod)%mod)%mod;
                        }
                    }
                }
            }
            printf("%lld
    ",ans);
        }
    }
    
     
  • 相关阅读:
    Android学习小Demo一个显示行线的自定义EditText
    Android中自定义checkbox样式
    android圆角View实现及不同版本这间的兼容
    android下大文件分割上传
    drwtsn32.exe 遇到问题须要关闭。我们对此引起的不便表示抱歉
    【分享】深入浅出WPF全系列教程及源码
    iOS国际化时遇到的错误:read failed: the data couldn&#39;t be read because it isn&#39;t in the correct format.
    void及void指针含义的深刻解析
    堆和栈的差别(转过无数次的文章)
    sizeof,终极无惑(上)
  • 原文地址:https://www.cnblogs.com/mountaink/p/11635215.html
Copyright © 2011-2022 走看看