题目链接:http://www.spoj.com/problems/MSTS/
题目大意:
最小生成树计数
算法:
首先要明白一个性质:
所有最小生成树的权值为ci的边的数量ni和所连接的点集S是一样。
由此可以计算每种权值的边拿出ni个构成S的最小生成树的数量。
那么我们把权值相同的边看成一组,我们先从小到大的求每个组的联通块中生成树的数量。
然后把每个组内的边进行krustal合并,形成一个新图。
我们再对这个图进行生成树计数,最后全部相乘。
关于生成树计数,请参考周冬的论文《生成树的计数及其应用》和bjin的论文《欧几里得算法的应用》。
代码如下:
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define mod 31011
using namespace std;
vector<pair<int,pair<int,int> > > edge;
int M[105][105],p[105];
int n,m;
int findr(int x)
{
if(p[x]<0)
return x;
return p[x]=findr(p[x]);
}
long long det(vector<pair<int,int> >& es)
{
vector<int>hash;
for