题目: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 ;
}

最新文章

  1. BlockingQueue 阻塞队列,很有用的一种
  2. R语言实战(三)基本图形与基本统计分析
  3. 在Xcode中使用Git进行源码版本控制
  4. Activity使用Serializable传递对象实例
  5. Hadoop集群(第7期)_Eclipse开发环境设置
  6. 【20161030la 】总结
  7. phome_enewsclass 数据表字段解释(栏目主表)
  8. PHP绿色集成环境在云服务器上的应用,PHPWAMP在服务器上搭建网站案例
  9. BNU OJ 50999 BQG&#39;s Approaching Deadline
  10. RPM安装软件
  11. 【笔记】【VSCode】Windows下VSCode编译调试c/c++
  12. Javascript - Jquery - 动画
  13. JS数字指定长度不足前补零的实现
  14. matplotlib之直接保存图片
  15. Django实现websocket完成实时通讯,聊天室,在线客服等
  16. Java BIO、NIO、AIO 学习
  17. How to: Display a Non-Persistent Object&#39;s List View from the Navigation
  18. python网络编程--线程event
  19. Python笔记 #11# 统计图定制化
  20. fzu_oop_east 第一次作业

热门文章

  1. allegro中查看寄生参数
  2. devstck 部署OpenStack Queens allinone
  3. NYOJ-768移位密码,最简单的代替密码;
  4. windows 下 iptables
  5. 2018/2/16 解析Logback的AppenderBase源码,并举一反三的实现Logback扩展功能的思路,以及它的实际业务应用场景
  6. codeforces Gym 100971 A、B、C、F、G、K、L
  7. Jquery那些事
  8. 使用HttpClient调用第三方接口
  9. wget: unable to resolve host address “mirrors.163.com” 的解决办法
  10. Maven公共仓库/镜像站收集及使用技巧