1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
| #include<bits/stdc++.h>
using namespace std;
//https://codeforces.com/contest/724/problem/G
const int maxn=1e5+4;
const int maxm=4e5+4;
const int maxp=62;
const int mod=1e9+7;
#define ll long long
struct edge{
int to,next; //to是该边指向的点,next是该边的上一条边的下标
ll val;
edge(){ to=0,next=-1,val=0;}
}es[maxm];
int head[maxn]; //head[i]是i点发出的最后一条边的下标
int cnt;
int n,m;
ll base[maxp];
ll p[maxp];
int r; //线性基数量
ll circle[maxm],dep[maxn];
int cir;
inline void add(int u,int v,ll t){
es[cnt].to=v;
es[cnt].val=t;
es[cnt].next=head[u]; //next指向上个head
head[u]=cnt++; //当前加入的边是head
}
int cover[maxn]; //记录本次dfs覆盖了哪些点
int cntc;
void dfs(int u,int fa,ll cur){
cover[cntc++]=u;
//cur是当前点到根的异或和
dep[u]=cur;
for(int i=head[u];i!=-1;i=es[i].next){
int v=es[i].to;
if(es[i].to==fa)
continue;
if(dep[es[i].to]==-1){
dfs(v,u,cur^es[i].val);
}else{
//重复到达某个点,说明有环,添加它的值
circle[cir++]=dep[u]^dep[v]^es[i].val;
}
}
}
inline void linearBase(){
memset(p,0,sizeof(p));
r=0;
for(int i=0;i<cir;i++){
ll x=circle[i];
for(int j=maxp-1;j>=0;j--){
if(x&(1ll<<j)){
if(!p[j]){
p[j]=x;
break;
}
x^=p[j];
}
if(!x) break;
}
}
for(int i=0;i<maxp;i++)
if(p[i]) r++;
}
ll ans;
inline void solve(){
linearBase();
int i,j;
ll tot[2];
for(i=0;i<maxp;i++){
tot[0]=0,tot[1]=0;
for(j=0;j<cntc;j++){
if(dep[cover[j]]&(1ll<<i)) tot[1]++;
else tot[0]++;
}
ll tmp=(tot[0]*(tot[0]-1)/2%mod+tot[1]*(tot[1]-1)/2)%mod; //路径异或值该位同为1或0的对子数量
bool f=false; //true:存在一个线性基该位为1
for(j=0;j<maxp;j++){
if(p[j]&(1ll<<i)){
f=true; break;
}
}
if(f){
tmp=(tmp*base[r-1]%mod)*base[i]%mod; //线性基能带来2^(r-1)个2^i值
ans=(ans+tmp)%mod;
}
tmp=tot[0]*tot[1]%mod;
if(f){
tmp=(tmp*base[r-1]%mod); //在该位有线性基,所以只有一半的能做贡献
}else{
tmp=tmp*base[r]%mod; //此时由于线性基该位为0,所以2^r个线性基全做贡献
}
tmp=tmp*base[i]%mod;
ans=(ans+tmp)%mod;
}
}
int main(){
cin>>n>>m;
int u,v;
ll t;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++){
scanf("%d%d%lld",&u,&v,&t);
add(u,v,t);
add(v,u,t);
}
base[0]=1;
for(int i=1;i<maxp;i++) base[i]=(base[i-1]*2)%mod;
memset(dep,-1,sizeof(dep));
for(int i=1;i<=n;i++){
if(dep[i]==-1){
cntc=0; //清除上个联通块中的点
cir=0; //清除上个联通块中的环
dfs(i,0,0);
solve();
}
}
cout<<ans%mod<<endl;
return 0;
}
|