bzoj1016 [JSOI2008]最小生成树计数——Kruskal+矩阵树定理
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016
从 Kruskal 算法的过程来考虑产生多种方案的原因,就是边权相同的边有一样的功能,从而带来了多种选择;
对于每一层次(边权相同)的边来说,它们最终会把图进一步连通;
所以在这一层之前缩好点,看看这一层连接出几个新连通块,对于每个连通块内部做矩阵树定理求生成树个数,再乘法原理乘起来即可;
注意高斯消元的矩阵不能直接用原图的点标号等,求行列式会出错;
疑惑:以及高斯消元 return 时为什么要加个 abs?
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
vector<int>v[];
int n,m,fa[],pa[],a[][],c[][],ans=,mod=;
bool vis[];
struct N{
int hd,to,w;
N(int h=,int t=,int w=):hd(h),to(t),w(w) {}
}edge[];
bool cmp(N x,N y){return x.w<y.w;}
int find(int x,int f[]){return f[x]==x?x:find(f[x],f);}//
int gauss(int n)
{
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
a[i][j]%=mod;//
int fl=,ret=;
for(int i=;i<=n;i++)
{
int t=i;
for(int j=i+;j<=n;j++)
if(abs(a[j][i])>abs(a[t][i]))t=j;//abs
if(t!=i)
{
fl^=;
for(int j=i;j<=n;j++)swap(a[i][j],a[t][j]);
}
for(int j=i+;j<=n;j++)
while(a[j][i])
{
int tmp=a[i][i]/a[j][i];
for(int k=i;k<=n;k++)
{
int tp=a[i][k]; a[i][k]=a[j][k];//a=b
a[j][k]=(tp-a[j][k]*tmp)%mod;//b=a%b
}
fl^=;
}
(ret*=a[i][i])%=mod;
}
return (abs(ret)%mod+mod)%mod;//abs!?
// return ret;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)fa[i]=i;
for(int i=,x,y,z;i<=m;i++)
scanf("%d%d%d",&edge[i].hd,&edge[i].to,&edge[i].w);
sort(edge+,edge+m+,cmp);
for(int i=;i<=m+;i++)
{
if(edge[i].w!=edge[i-].w || i==m+)
{
for(int j=;j<=n;j++)
{
if(!vis[j])continue;
int f1=find(j,pa);
v[f1].push_back(j);//v是点的集合
vis[j]=;
}
for(int j=;j<=n;j++)
{
if(v[j].size()<=)continue;
memset(a,,sizeof a);
int siz=v[j].size();
for(int k=;k<siz;k++)
for(int l=k+;l<siz;l++)
{
int x=v[j][k],y=v[j][l],t=c[x][y];
// a[x][x]+=t; a[y][y]+=t;
// a[x][y]-=t; a[y][x]-=t;
a[k+][k+]+=t; a[l+][l+]+=t;
a[k+][l+]-=t; a[l+][k+]-=t;//!
}
(ans*=gauss(siz-))%=mod;
// (ans*=gauss(n-1))%=mod;
for(int k=;k<siz;k++)fa[v[j][k]]=j;
}
for(int j=;j<=n;j++)
{
pa[j]=fa[j]=find(j,fa);
v[j].clear();
}
}
int f1=find(edge[i].hd,fa),f2=find(edge[i].to,fa);
if(f1==f2)continue;
pa[find(f1,pa)]=find(f2,pa); vis[f1]=; vis[f2]=;
c[f1][f2]++; c[f2][f1]++;
}
for(int i=;i<=n;i++)//!
if(find(i,fa)!=find(i-,fa)){printf(""); return ;}
printf("%d",ans);
return ;
}
bzoj1016 [JSOI2008]最小生成树计数——Kruskal+矩阵树定理的更多相关文章
- [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- 洛谷4208 JSOI2008最小生成树计数(矩阵树定理+高斯消元)
qwq 这个题目真的是很好的一个题啊 qwq 其实一开始想这个题,肯定是无从下手. 首先,我们会发现,对于无向图的一个最小生成树来说,只有当存在一些边与内部的某些边权值相同的时候且能等效替代的时候,才 ...
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等 就是说如果一种方案中权值为1的边有n条 ...
- BZOJ 1016 最小生成树计数(矩阵树定理)
我们把边从小到大排序,然后依次插入一种权值的边,然后把每一个联通块合并. 然后当一次插入的边不止一条时做矩阵树定理就行了.算出有多少种生成树就行了. 剩下的交给乘法原理. 实现一不小心就会让程序变得很 ...
- [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- 【Matrix-tree定理】【并查集】【kruscal算法】bzoj1016 [JSOI2008]最小生成树计数
题意:求一个图的最小生成树个数. 矩阵树定理:一张无向图的生成树个数 = (度数矩阵 - 邻接矩阵)的任意一个n-1主子式的值. 度数矩阵除了对角线上D[i][i]为i的度数(不计自环)外,其他位置是 ...
- bzoj1016 [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3517 Solved: 1396[Submit][St ...
- 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)
传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...
随机推荐
- 第二十三节:scrapy爬虫识别验证码(二)图片验证码识别
图片验证码基本上是有数字和字母或者数字或者字母组成的字符串,然后通过一些干扰线的绘制而形成图片验证码. 例如:知网的注册就有图片验证码 首先我们需要获取验证码图片,通过开发者工具我们可以得到验证码ur ...
- CentOS7 Failed to start LSB: Bring up/down解决方法(真正有效的方法)
刚刚装好的虚拟机突然不能上网了,报错很诡异,具体报错如下: /etc/init.d/network restart Restarting network (via systemctl): Job f ...
- Eclipse调试相关
Eclipse调试相关 F5 step into就是单步执行,遇到子函数就进入并且继续单步执行. F6 step over是在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个 ...
- android源码mm时的编译错误no ruler to make target `out/target/common/obj/JAVA_LIBRARIES/xxxx/javalib.jar', needed by `out/target/common/obj/APPS/xxxx_intermediates/classes-full-debug.jar'. Stop.
瞧见没有,就因为多了这一个反斜杠,浪费了一下午时间找问题,哭了~~~~
- Educational Codeforces Round 41 B、C、D
http://codeforces.com/contest/961 B题 可以将长度为k的连续区间转化成1 求最大和 解析 简单尺取 #include <stdio.h> #include ...
- 恢复表数据的办法(delete删除可恢复,truncate不可恢复)
select * from table_name as of timestamp to_timestamp('2018-12-20 00:00:00', 'yyyy-mm-dd hh24:mi:ss' ...
- 洛谷 P2064 奇妙的汽车
P2064 奇妙的汽车 题目描述 你有着一辆奇妙的汽车,这辆汽车有着自动加速的功能.打个比方吧,第1天你驾驶着它可以行驶a路程,那么第2天你可以让它所走的路程增加到第1天的2~9倍(必须是其中一个整数 ...
- 旧瓶新酒之ngx_lua & fail2ban实现主动诱捕
服务器承担着业务运行及数据存储的重要作用,因此极易成为攻击者的首要目标.如何对业务服务器的安全进行防护,及时找出针对系统的攻击,并阻断攻击,最大程度地降低主机系统安全的风险程度,是企业安全从业人员面临 ...
- Windows Server2008 R2 设置NAT 让Hyper-V连接Internet
1.添加虚拟网卡,设置为内部,并且固定IP地址192.168.1.1 255.255.255.0 此为内网网卡 2.添加服务器角色:DHCP服务器,DNS服务器,网络策略和访问服务 3."网 ...
- Yarn 的工作流-创建一个新项目
Microsoft Windows [版本 10.0.16299.125] (c) Microsoft Corporation.保留所有权利. C:\Users\Administrator>cd ...