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=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = , mod = 1e9 + ;
struct Edge{ int to, nxt; LL w; } e[];
int head[N], En;
LL dis[N], b[], 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] = ;
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 = ; ~i; --i) {
if ((x >> i) & ) {
if (b[i]) x ^= b[i];
else {
b[i] = x;
break;
}
}
}
}
void Clear() {
memset(b, , 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 = ; i < (int)B.size(); ++i) Insert(B[i]);
LL cnt[] = {, }, r = , now;
for (int i = ; ~i; --i) if (b[i]) r ++;
for (int k = ; ~k; --k) {
bool flag = ; cnt[] = cnt[] = ;
for (int i = ; ~i; --i) if ((b[i] >> k) & ) flag = ;
for (int i = ; i < (int)A.size(); ++i) cnt[(dis[A[i]] >> k) & ] ++;
now = cnt[] * (cnt[] - ) / + cnt[] * (cnt[] - ) / ; now %= mod;
if (flag) {
if (r >= ) mul(now, mi[r - ]);
mul(now, mi[k]);
add(Ans, now);
}
now = cnt[] * cnt[];
if (flag) { if (r >= ) mul(now, mi[r - ]); }
else mul(now, mi[r]);
mul(now, mi[k]);
add(Ans, now);
}
Clear();
} int main() {
int n = read(), m = read();
mi[] = ;
for (int i = ; i <= ; ++i) mi[i] = mi[i - ] * % mod;
for (int i = ; i <= m; ++i) add_edge();
for (int i = ; i <= n; ++i) {
if (!vis[i]) {
dfs(i);
Calc();
}
}
cout << Ans;
return ;
}
05-07 15:33