JZOJ5899. 【NOIP2018模拟10.6】资源运输

在这里插入图片描述
在这里插入图片描述

题解

题目的意思就求一个图的生成树个数,还有所有生成树的权值乘积和。
其实这题是一道非常简单的题目,只要知道矩阵树定理就好了。

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define ll long long
#define N 303
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
	n=0;
	ch=G();
	while((ch<'0' || ch>'9') && ch!='-')ch=G();
	ll w=1;
	if(ch=='-')w=-1,ch=G();
	while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
	n*=w;
}

const int mo=998244353;
int n,m,x,y,z,d[N];
int a[N][N],b[N][N];
ll ans;

ll ksm(ll x,int y)
{
	ll s=1;
	for(;y;y>>=1,x=x*x%mo)
		if(y&1)s=s*x%mo;
	return s;
}

ll calc()
{
	for(int i=1;i<n;i++)
		for(int j=i+1;j<n;j++)
		{
			ll p=ksm(a[i][i],mo-2)*a[j][i]%mo;
			for(int k=i;k<n;k++)
				a[j][k]=(a[j][k]-p*a[i][k]%mo+mo)%mo;
		}
	ll s=1;
	for(int i=1;i<n;i++)
		s=s*a[i][i]%mo;
	return s;
}

int main()
{
	freopen("avg.in","r",stdin);
	freopen("avg.out","w",stdout);
	
	read(n);read(m);
	for(int i=1;i<=m;i++)
	{
		read(x);read(y);read(z);
		a[x][y]--;a[x][x]++;
		a[y][x]--;a[y][y]++;
		b[x][y]=(b[x][y]-z+mo)%mo;
		b[x][x]=(b[x][x]+z)%mo;
		b[y][x]=(b[y][x]-z+mo)%mo;
		b[y][y]=(b[y][y]+z)%mo;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			a[i][j]=(a[i][j]+mo)%mo;
	
	ans=ksm(calc(),mo-2);
	memcpy(a,b,sizeof(b));
	ans=ans*calc()%mo;
	printf("%lld",ans);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lijf2001/article/details/82990092