题目大意:
要你求一张图的生成树的边权乘积期望。
思路:
这题是一个矩阵树和变元矩阵树定理的应用题,矩阵树可以求出来生成树的数量,变元后的矩阵树可以求出所有生成树乘积和,然后除一下就好了。
矩阵树写法如下:
先定义两个矩阵,一个是度数矩阵,一个是连接矩阵,用度数矩阵剪掉连接矩阵,然后去掉一行一列,然后高斯消元,把对角线所有数乘起来就好了。
程序:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
#define mo 998244353
#define N 305
using namespace std;
int n,m,x,y,z;
LL a[N][N],b[N][N];
LL mul(LL x,int y){
if (y==1) return x;
LL o=mul(x,y/2);
o=(o*o)%mo;
if (y%2==1) o=(o*x)%mo;
return o;
}
LL det(){
LL ans=1;
for (int i=1;i<=n;i++){
LL inv=mul(a[i][i],mo-2);
for (int j=i+1;j<=n;j++){
LL rate=a[j][i]*inv%mo;
for (int k=i;k<=n;k++){
a[j][k]=(a[j][k]+mo-rate*a[i][k]%mo)%mo;
}
}
ans=(ans*a[i][i])%mo;
}
return ans;
}
int main(){
freopen("avg.in","r",stdin);
freopen("avg.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&x,&y,&z);
a[x][y]=mo-1;
a[y][x]=mo-1;
a[x][x]++;
a[y][y]++;
b[x][y]=mo-z;
b[y][x]=mo-z;
b[x][x]=(b[x][x]+z)%mo;
b[y][y]=(b[y][y]+z)%mo;
}
n--;
LL B=det();
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a[i][j]=b[i][j];
LL A=det();
printf("%lld",A*mul(B,mo-2)%mo);
}