题意是给定n个点,m条边的无向图,求最小生成树的个数对p取模。

用kruscal计算最小生成树时,每次取连接了两个不同联通块的最小的边。也就是先处理d1条c1长度的边,再处理d2条c2长度的边。长度相同的边无论怎么选,最大联通情况都是固定的。 分别对ci长度的边产生的几个联通块计算生成树数量再乘起来,然后把这些联通块缩点,再计算ci+1长度的边。

生成树计数用Matrix-Tree定理,上一篇是无重边的,这题的缩点后是会产生重边的,Matrix-tree也适用:   //抄别人博客的

Kirchhoff矩阵任意n-1阶子矩阵的行列式的绝对值就是无向图的生成树的数量。

Kirchhoff矩阵的定义是度数矩阵-邻接矩阵。

1、G的度数矩阵D[G]:n*n的矩阵,Dii等于Vi的度数,其余为0。
2、G的邻接矩阵A[G]:n*n的矩阵, Vi、Vj之间有边直接相连,则 Aij=ij之间的边数,否则为0。

并查集fa[i]是当前长度之前,节点所属的联通块,ka[i]是当前长度的边连接后它在的联通块。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N=;
const int M=;
ll n,m,p,ans;
vector<int>gra[N];
struct edge{
int u,v,w;
}e[M];
int cmp(edge a,edge b){
return a.w<b.w;
}
ll mat[N][N],g[N][N];
ll fa[N],ka[N],vis[N];
ll det(ll c[][N],ll n){
ll i,j,k,t,ret=;
for(i=;i<n;i++)
for(j=;j<n;j++) c[i][j]%=p;
for(i=; i<n; i++){
for(j=i+; j<n; j++)
while(c[j][i]){
t=c[i][i]/c[j][i];
for(k=i; k<n; k++)
c[i][k]=(c[i][k]-c[j][k]*t)%p;
swap(c[i],c[j]);
ret=-ret;
}
if(c[i][i]==)
return 0L;
ret=ret*c[i][i]%p;
}
return (ret+p)%p;
}
ll find(ll a,ll f[]){
return f[a]==a?a:find(f[a],f);
}
void matrix_tree(){//对当前长度的边连接的每个联通块计算生成树个数
for(int i=;i<n;i++)if(vis[i]){//当前长度的边连接了i节点
gra[find(i,ka)].push_back(i);//将i节点压入所属的联通块
vis[i]=;//一边清空vis数组
}
for(int i=;i<n;i++)
if(gra[i].size()>){//联通块的点数为1时生成树数量是1
memset(mat,,sizeof mat);//清空矩阵
int len=gra[i].size();
for(int j=;j<len;j++)
for(int k=j+;k<len;k++){//构造这个联通块的矩阵(有重边)
int u=gra[i][j],v=gra[i][k];
if(g[u][v]){
mat[k][j]=(mat[j][k]-=g[u][v]);
mat[k][k]+=g[u][v];mat[j][j]+=g[u][v];
}
}
ans=ans*det(mat,gra[i].size()-)%p;
for(int j=;j<len;j++)fa[gra[i][j]]=i;//缩点
}
for(int i=;i<n;i++)
{
gra[i].clear();
ka[i]=fa[i]=find(i,fa);
}
}
int main(){
while(scanf("%lld%lld%lld",&n,&m,&p),n){
for(int i=;i<m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
u--;v--;
e[i]=(edge){u,v,w};
}
sort(e,e+m,cmp);
memset(g,,sizeof g);
ans=;
for(ll i=;i<n;i++)ka[i]=fa[i]=i;
for(ll i=;i<=m;i++){//边从小到大加入
if(i&&e[i].w!=e[i-].w||i==m)//处理完长度为e[i-1].w的所有边
matrix_tree();//计算生成树
ll u=find(e[i].u,fa),v=find(e[i].v,fa);//连的两个缩点后的点
if(u!=v)//如果不是一个
{
vis[v]=vis[u]=;
ka[find(u,ka)]=find(v,ka);//两个分量在一个联通块里。
g[u][v]++,g[v][u]++;//邻接矩阵
}
}
int flag=;
for(int i=;i<n;i++)if(fa[i]!=fa[i-])flag=;
printf("%lld\n",flag?ans%p:);//注意p可能为1,这样m=0时如果ans不%p就会输出1
}
}

最小生成树计数 模板 hdu 4408的更多相关文章

  1. 最小生成树计数 bzoj 1016

    最小生成树计数 (1s 128M) award [问题描述] 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一 ...

  2. 【bzoj1016】 JSOI2008—最小生成树计数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1016 (题目链接) 题意 求图的最小生成树计数. Solution %了下题解,发现要写矩阵树,15 ...

  3. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

  4. bzoj1016 [JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3517  Solved: 1396[Submit][St ...

  5. 【BZOJ】【1016】【JSOI2008】最小生成树计数

    Kruskal/并查集+枚举 唉我还是too naive,orz Hzwer 一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的 ...

  6. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

    最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小 ...

  7. BZOJ_1016_[JSOI2008]_最小生成树计数_(dfs+乘法原理)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1016 给出一张图,其中具有相同权值的边的数目不超过10,求最小生成树的个数. 分析 生成树的计 ...

  8. BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

  9. 1016: [JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6200  Solved: 2518[Submit][St ...

随机推荐

  1. 2018ICPC南京站Problem G. Pyramid

    题意: 找有多少个等边三角形 解析: 首先打标找规律,然后对式子求差分 0,1,5,15,35,70,126,210... 1,4,10,20,35,56... 3,6,10,15,21... 3,4 ...

  2. GNU Screen使用

    基本使用 SSH时可以方便地resume工作 # open new screen session screen # restore screen -r  Steps Using GNU Screen ...

  3. Android Q 接入 MQTT

    Android Q 接入 MQTT 首先在APP 下引入mqtt的库 implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1 ...

  4. Spring Data JPA介绍与简单案例

    一.Spring Data JPA介绍 可以理解为JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL(Java Persistence Query Languag ...

  5. SpringBoot学习- 6、MetaData描述无法tip显示问题

    SpringBoot学习足迹 (一)先说说现象 1.在application.properties可以定义属性并在MetaData中增加description 如 生成additional-sprin ...

  6. tcp与http协议 以及python的实现

    htpp协议 Rquest Headers格式: 请求方法空格URL空格协议版本回车符换行符 头部字段名:值回车符换行符 ··· 头部字段名:值回车符换行符 回车符换行符 请求数据 socket网络聊 ...

  7. Python环境搭建(win)——Pycharm(破解+汉化)

    Pycharm搭建方法(破解+汉化): 本文以pycharm2019.2为例 写在前面:有能力的朋友,希望大家支持正版. IDE是集成开发环境 “Integrated Development Envi ...

  8. [POI2004] PRZ - 状压dp

    很简单的子集枚举状压dp 这个 (j-1)&i 的子集枚举是真的骚气 #include <bits/stdc++.h> using namespace std; int W,n,t ...

  9. python itertool 浅谈迭代工具

    1.概述 Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数. 首先,我们看看itertools提供的几个“无限”迭代器: import itertools natuals ...

  10. spring boot 运行错误: 找不到或无法加载主类

    在项目根目录运行 mvn clean install 进行重新编译 不行的话就删了原有的启动配置,重新配置启动.