CF 724 G. Xor-matic Number of the Graph

G. Xor-matic Number of the Graph

链接

题意:

  给定一个无向图,一个interesting的三元环(u,v,s)满足,从u到v的路径上的异或和等于s,三元环的权值为s,求所有三元环权值之和。

分析:

  求出所有的三元环,建立线性基,然后逐位求每一位的贡献。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;

inline LL read() {
    LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 100005, mod = 1e9 + 7;
struct Edge{ int to, nxt; LL w; } e[500005];
int head[N], En;
LL dis[N], b[65], mi[N], Ans;
bool vis[N];
vector<LL> B;
vector<int> A;

inline void add_edge() {
    int u = read(), v = read(); LL w = read();
    ++En; e[En].to = v, e[En].w = w; e[En].nxt = head[u]; head[u] = En;
    ++En; e[En].to = u, e[En].w = w; e[En].nxt = head[v]; head[v] = En;
}
void dfs(int u) {
    A.push_back(u);
    vis[u] = 1;
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (vis[v]) B.push_back(dis[u] ^ e[i].w ^ dis[v]);
        else {
            dis[v] = dis[u] ^ e[i].w;
            dfs(v);
        }
    }
}
void Insert(LL x) {
    for (int i = 60; ~i; --i) {
        if ((x >> i) & 1) {
            if (b[i]) x ^= b[i]; 
            else {
                b[i] = x; 
                break; 
            }
        }
    }
}
void Clear() {
    memset(b, 0, sizeof(b));
    A.clear(), B.clear();
}
inline void mul(LL &x,LL y) { x *= y; x %= mod; }
inline void add(LL &x,LL y) { x += y; if (x >= mod) x -= mod; }

void Calc() {
    for (int i = 0; i < (int)B.size(); ++i) Insert(B[i]);
    LL cnt[2] = {0, 0}, r = 0, now;
    for (int i = 60; ~i; --i) if (b[i]) r ++;
    for (int k = 60; ~k; --k) {
        bool flag = 0; cnt[0] = cnt[1] = 0;
        for (int i = 60; ~i; --i) if ((b[i] >> k) & 1) flag = 1;
        for (int i = 0; i < (int)A.size(); ++i) cnt[(dis[A[i]] >> k) & 1] ++;
        now = cnt[0] * (cnt[0] - 1) / 2 + cnt[1] * (cnt[1] - 1) / 2; now %= mod;
        if (flag) {
            if (r >= 1) mul(now, mi[r - 1]); 
            mul(now, mi[k]);
            add(Ans, now);
        }
        now = cnt[0] * cnt[1];
        if (flag) { if (r >= 1) mul(now, mi[r - 1]); }
        else mul(now, mi[r]);
        mul(now, mi[k]);
        add(Ans, now);
    }
    Clear();
}

int main() {
    int n = read(), m = read();
    mi[0] = 1; 
    for (int i = 1; i <= 62; ++i) mi[i] = mi[i - 1] * 2 % mod;
    for (int i = 1; i <= m; ++i) add_edge();
    for (int i = 1; i <= n; ++i) {
        if (!vis[i]) {
            dfs(i);
            Calc();
        }
    }
    cout << Ans;
    return 0;
}

 

posted @ 2019-02-15 09:05  MJT12044  阅读(182)  评论(0编辑  收藏  举报