题意:
给定n个点m条边的无向图,随机取出一棵生成树。
定义生成树的权值为生成树边权的位与&。
问取出的生成树权值期望。
数据范围:n<=100,m<=1e4
解法:
题解:
行列式:
交换两行/列,行列式的值取反
将某行/列乘上k,行列式也乘上k
用一行的倍数减去另一行,行列式值不变
将n阶矩阵化为上三角矩阵(右上角),行列式的值就是对角线元素乘积
---
无向图矩阵树定理:(有向图的不挂了)
前提:
图允许重边,不允许自环
定义:
1.图G的度数矩阵D(G):
D[i][i]=de[i],D[i][j]=0,其中i!=j
2.图G的邻接矩阵A(G):
A[i][j]=e(i,j),其中e(i,j)表示i到j的边数,且i!=j
3.图G的Kirchhoff矩阵L(G):
L[i][j]=D[i][j]-A[i][j]
实际运用中构造L(G)矩阵的方法:
对于边(u,v):
L[u][u]++,L[v][v]++,L[u][v]--,L[v][u]--.
(L[x][x]表示x点的度数,L[x][y]表示x到y的边数取反(x!=y))
4.图G的生成树数量为t(G)
定理:
1.L(G)的所有n-1阶主子式都相等
2.t(G)=L(G)的n-1个非零特征值乘积
上三角矩阵的特征值就是对角线元素
n-1个非零特征值乘积其实就是任意找一个n-1阶主子式,化为上三角矩阵后计算对角线元素乘积,
(其实就是选择一个i,删掉第i行第i列,方便起见一般是删掉最后一行和最后一列)
---
注意事项:
行列式一定要是缩为上三角(右上角)
矩阵树定理需要删去最后一行和最后一列,n阶矩阵计算前n-1阶的行列式就行了
(删除第i行和第i列也可以,但是删最后一行和最后一列比较方便)
---
ps:
本题需要取模,而高斯消元中有除法,因此用了辗转相除法(欧几里得算法),
但是这题的模数是质数,似乎可以直接用逆元
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
typedef pair<int,int> PI;
const int maxm=1e5+5;
const int mod=998244353;
struct Node{
int a,b,c;
}e[maxm];
int n,m;
int K[105][105];
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int guass(int n){
int ans=1;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
while(K[j][i]){//直到为0
int t=K[i][i]/K[j][i];//计算第i行对应的数是第j行的几倍
for(int k=i;k<=n;k++){//一个一个消去并交换数字(消去之后之前的位置变小)
K[i][k]=(K[i][k]-t*K[j][k]%mod+mod)%mod;
swap(K[i][k],K[j][k]);//交换
}
ans=-ans;//交换行,行列式的值取反
}
}
if(!K[i][i])return 0;//生成树数量为0
ans=(ans*K[i][i]%mod+mod)%mod;//上三角行列式(右上角)的值为对角线乘积
}
return ans;
}
signed main(){
int T;cin>>T;
while(T--){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>e[i].a>>e[i].b>>e[i].c;
}
int ans=0;
for(int k=0;k<=30;k++){
memset(K,0,sizeof K);
for(int i=1;i<=m;i++){
int a=e[i].a,b=e[i].b,c=(e[i].c>>k&1);
K[a][a]+=c;
K[b][b]+=c;
K[a][b]-=c;
K[b][a]-=c;
}
ans=(ans+guass(n-1)*(1<<k)%mod)%mod;
}
memset(K,0,sizeof K);
for(int i=1;i<=m;i++){
int a=e[i].a,b=e[i].b;
K[a][a]++;
K[b][b]++;
K[a][b]--;
K[b][a]--;
}
int cnt=guass(n-1);
ans=ans*ppow(cnt,mod-2,mod)%mod;
ans=(ans%mod+mod)%mod;
cout<<ans<<endl;
}
return 0;
}