Description

Input

Output

HINT

题解:

一种很直观的想法是通过矩阵生成树求树形图方法数ans以及不包含某一条边i的树形图方法数ans[i],则答案为Σ(ans-ans[i])*w[i]。

对于树形图,矩阵生成树的建立方法是:将有向边(u,v)加入,即inc(A[u,u])(如果是要求n能够走到所有点则inc(A[v,v])),dec(A[u,v])。

删去第n行与第n列后,求行列式(即m[n,n],m为余子式矩阵)。

对于要删去某条边情况下的m[n,n],只要修改矩阵的两项,再求m[n,n]。因为总要删去第n行与第n列,所以只要保留(n-1)*(n-1)的矩阵,每次求整个矩阵的行列式即可。

但是这样做肯定会TLE,考虑使用伴随矩阵去优化。

有公式:

其中,A为原矩阵,A*为A的伴随矩阵,即A的代数余子式矩阵cof A的转置。(cof A[i,j]=(-1)^(i+j)*m[i,j])

我们通过高斯消元求行列式以及矩阵求逆,计算出A*,转置得到cof A。

对矩阵行展开求行列式的公式是:

当删去一条边时,只修改了A[u,u]与A[u,v],它们都在第u行,所以cof A的第u行不变。

我们可以按第u行展开,O(n)求解。多预处理一些东西,甚至可以O(1)求解。

代码:

 #include<bits/stdc++.h>
using namespace std;
const int mo=;
int n,m;
int ksm(int xx,int yy)
{
int zz=;
while(yy)
{
if(yy&)zz=(1ll*xx*zz)%mo;
yy>>=; xx=(1ll*xx*xx)%mo;
}
return zz;
}
int t[][];
struct matrix
{
int a[][];
void cheng(matrix &b) //矩阵乘法
{
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
t[i][j]=;
for(int k=;k<=n;k++)t[i][j]=(1ll*a[i][k]*b.a[k][j]+t[i][j])%mo;
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)a[i][j]=t[i][j];
}
void hswap(int i,int j) //矩阵行交换
{
for(int k=;k<=*n;k++){ int t=a[i][k]; a[i][k]=a[j][k]; a[j][k]=t; }
}
void hadd(int i,int j,int l) //矩阵行之间加减
{
for(int k=;k<=*n;k++)a[j][k]=(1ll*l*a[i][k]+a[j][k])%mo;
}
void qiuni() //矩阵求逆
{
int flag=;
for(int i=;i<=n;i++)a[i][i+n]=;
for(int i=;i<=n;i++)
{
int j=i; while((j<=n)and(a[j][i]==))j++;
if(j>n){ flag=; break; }
if(i!=j)hswap(i,j);
for(int j=i+;j<=n;j++)if(a[j][i]!=)
{
int xx=(1ll*a[j][i]*ksm(a[i][i],mo-))%mo;
hadd(i,j,(-xx)%mo);
}
}
if(flag==){ for(int i=;i<=n;i++)for(int j=;j<=*n;j++)a[i][j]=; return; }
for(int i=n;i>=;i--)
{
int xx=ksm(a[i][i],mo-); hadd(i,i,(xx-)%mo);
for(int j=;j<i;j++)if(a[j][i]!=)hadd(i,j,(-a[j][i])%mo);
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){ a[i][j]=a[i][j+n]; a[i][j+n]=; }
}
int det() //求矩阵行列式
{
int ans=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)t[i][j]=a[i][j];
for(int i=;i<=n;i++)
{
int j=i; while((j<=n)and(a[j][i]==))j++;
if(j>n)break;
if(i!=j)hswap(i,j),ans=-ans;
for(int j=i+;j<=n;j++)if(a[j][i]!=)
{
int xx=(1ll*a[j][i]*ksm(a[i][i],mo-))%mo;
hadd(i,j,(-xx)%mo);
}
}
for(int i=;i<=n;i++)ans=(1ll*ans*a[i][i])%mo;
for(int i=;i<=n;i++)for(int j=;j<=n;j++)a[i][j]=t[i][j];
return ans;
}
void zhuanzhi() //矩阵转置
{
for(int i=;i<=n;i++)
for(int j=;j<i;j++){ int t=a[i][j]; a[i][j]=a[j][i]; a[j][i]=t; }
}
} x,y;
int b[][],w[];
int ans,ans2,tot;
int main()
{
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)scanf("%d%d%d",&b[i][],&b[i][],&w[i]);
for(int i=;i<=m;i++)
if(b[i][]<n){ (x.a[b[i][]][b[i][]]+=)%=mo; if(b[i][]<n)(x.a[b[i][]][b[i][]]-=)%=mo; }
n--; int ans=x.det();
int ni=ksm(ans,mo-);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)y.a[i][j]=(1ll*x.a[i][j]*ni)%mo;
y.qiuni(); y.zhuanzhi();
for(int i=;i<=m;i++)
if(b[i][]<=n)
{
ans2=;
(x.a[b[i][]][b[i][]]-=)%=mo; if(b[i][]<=n)(x.a[b[i][]][b[i][]]+=)%=mo;
for(int j=;j<=n;j++)
ans2=(1ll*x.a[b[i][]][j]*y.a[b[i][]][j]+ans2)%mo;
tot=(1ll*(ans-ans2)*w[i]+tot)%mo;
(x.a[b[i][]][b[i][]]+=)%=mo; if(b[i][]<=n)(x.a[b[i][]][b[i][]]-=)%=mo;
}
tot=(tot+mo)%mo;
printf("%d\n",tot);
}

JZOJ5153:树形图求和的更多相关文章

  1. Java程序:从命令行接收多个数字,求和并输出结果

    一.设计思想:由于命令行接收的是字符串类型,因此应先将字符串类型转化为整型或其他字符型,然后利用for循环求和并输出结果 二.程序流程图: 三.源程序代码:   //王荣荣 2016/9/23     ...

  2. Java之递归求和的两张方法

    方法一: package com.smbea.demo; public class Student { private int sum = 0; /** * 递归求和 * @param num */ ...

  3. EXCEL中对1个单元格中多个数字求和

    如A1=3779.3759.3769.3781.3750,A2对A1中4个数字求和怎么求!请高手赐教! 方法一:在B1中输入公式=SUM(MID(A1,{1,6,11,16,21},4)*1) 方法二 ...

  4. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  5. 从sum()求和引发的思考

    sum()求和是一个非常简单的函数,以前我的写法是这样,我想大部分和我一样刚开始学习JS的同学写出来的也会是这样. function sum() { var total=null; for(var i ...

  6. //给定N个整数序列{A1,A2,A3...An},求函数f(i,j)=(k=i~j)Ak的求和

    //给定N个整数序列{A1,A2,A3...An},求函数f(i,j)=(k=i~j)Ak的求和 # include<stdio.h> void main() { ,sum1; ]={,- ...

  7. Ajax中get请求和post请求

    我们在使用Ajax向服务器发送数据时,可以采用Get方式请求服务器,也可以使用Post方式请求服务器,那么什么时候该采用Get方式,什么时候该采用Post方式呢? Get请求和Post请求的区别: 1 ...

  8. bzoj4349: 最小树形图

    最小树形图模板题…… 这种\(O(nm)\)的东西真的能考到么…… #include <bits/stdc++.h> #define N 60 #define INF 1000000000 ...

  9. POJ 2823 Sliding Window 线段树区间求和问题

    题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 本题数据量较大,不能用N建树,用n建树. 还有一种做法是单调 ...

随机推荐

  1. 【Luogu】【关卡2-1】简单的模拟(2017年10月)

    任务说明:开始普及组的训练!所谓模拟,就是直接根据题意编写,思维难度简单. 铺地毯 进制转换 多项式输出 机器翻译 排座椅 笨小猴 都是简单模拟题  

  2. ubuntu:beyond compare 4 This license key has been revoked 解决办法

    错误如图所示: 解决办法: (1)先用find命令找到bcompare所在位置:sudo find /home/ -name '*bcompare' ()进入 /home/whf/.config,删除 ...

  3. Tomcat 在IE中下载rar文件直接以乱码方式打开解决方案

    这几天一直很纳闷,在Tomcat部署的网站中的下载文件中,如果文件是rar类型的,一点击下载rar文件就直接打开,并且出现乱码,右键另存为浏览器也是默认为html格式,一直以为是浏览器IE的问题,后来 ...

  4. javascript null vs undefined

    这个是很古老的问题了. 一直存在争议,有些人认为,很多语言没用 undefined 也活的好好,为啥要 undefined 呢. 那有了 undefined 是否还需要 null 呢 ? typesc ...

  5. 关于axios中post请求提交后变成get的问题

    这个问题归结于自己的不细心,如下图. 头疼了好久,才发现是自己多写了一个s,在此记录一下.

  6. luoguP2709 小B的询问 [莫队]

    题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重 ...

  7. iptables对请求的URL作IP访问控制

    服务器运行环境是Tomcat,现在要实现的目的是,只允许特定的IP访问某个目录,一种方法是在tomcat配置文件server.conf中,使用RemoteAddrValve对虚拟主机做访问控制.另外一 ...

  8. STM32嵌入式开发学习笔记(七):串口通信(下)

    下面我们进行几个串口通信的实际应用. 实验一:发信实验,让开发板通过串口向电脑发送信息: #include <stdio.h> #include <stm32f10x.h> # ...

  9. jeecg接口开发及权限实现原理

    接口开发使用的框架 jeecg本身是基于 Spring MVC 框架搭建的,因此,使用 Spring MVC 框架的 RESTful API 功能来进行接口开发就是顺理成章的事了. 接口的拦截与鉴权 ...

  10. 数据挖掘 FP-tree算法C++实现及源码

    FP-growth挖掘算法 步骤一 扫描数据库,扫描数据库一次,得到频繁1-项集,把项按支持度递减排序,再一次扫描数据库,建立FP-tree 步骤二 对每个项,生成它的 条件模式库 步骤三 用条件模式 ...