【洛谷P6178】【模板】Matrix-Tree 定理
题目
题目链接:https://www.luogu.com.cn/problem/solution/P6178
给定一张 个结点 条边的带权图(可能为无向图,可能为有向图)。
定义其一个生成树 的权值为 中所有边权的乘积。
求其所有不同生成树的权值之和,对 取模。
思路
一般的矩阵树定理只能处理生成树数量的情况,但是这道题要求我们输出所有生成树权值之和。
我们可以把一条边 拆成 条 的边,这样原来的一棵生成树,假设其权值为 ,就变成了 棵生成树。此时只要求生成树数量即可。
对于有向边的情况,如果要求外向树,那么一条边 能贡献的就只有 和 。证明不会。
注意需要把自环去掉。
时间复杂度 。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=310,MOD=1e9+7;
int n,m,type;
ll g[N][N];
ll fpow(ll x,ll k)
{
ll ans=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) ans=ans*x%MOD;
return ans;
}
ll dit()
{
ll f=1,res=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
g[i][j]=(g[i][j]%MOD+MOD)%MOD;
for (int i=2;i<=n;i++)
{
for (int j=i;j<=n;j++)
if (g[j][i])
{
if (j!=i) f=-f;
for (int k=2;k<=n;k++)
swap(g[j][k],g[i][k]);
break;
}
ll inv=fpow(g[i][i],MOD-2);
for (int j=i+1;j<=n;j++)
if (g[j][i])
{
ll base=inv*g[j][i]%MOD;
for (int k=1;k<=n;k++)
g[j][k]=((g[j][k]-base*g[i][k])%MOD+MOD)%MOD;
}
}
for (int i=2;i<=n;i++) res=res*g[i][i]%MOD;
return (res*f%MOD+MOD)%MOD;
}
int main()
{
scanf("%d%d%d",&n,&m,&type);
for (int i=1,x,y,z;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
if (x==y) continue;
if (type)
g[x][y]-=z,g[y][y]+=z;
else
g[x][y]-=z,g[y][x]-=z,g[x][x]+=z,g[y][y]+=z;
}
printf("%lld",dit());
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· SQL Server统计信息更新会被阻塞或引起会话阻塞吗?
· 本地部署 DeepSeek:小白也能轻松搞定!
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 如何基于DeepSeek开展AI项目