传送门
Description
最小生成树计数
Solution
首先,考虑kruskal的过程,发现相同权值的边的集合对生成树的贡献是一样的
所以对权值排序按照从小到大的顺序
分别根据(Matrix-tree)做生成树计数
每个权值处理完,都缩点一下
为了好写,可以把很多联通块连在一起做
Code
/*最小生成树计数 */
#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"
"
#define dbg3(x) cerr<<#x<<"
"
using namespace std;
#define reg register
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int P=919260817,MN=305,ME=1e5+5;
int K[MN][MN];
int Mul(int x,int y){return (1ll*x*y)%P;}
int Add(int x,int y){return (x+y)%P;}
int Dec(int x,int y){return Add(x,P-y);}
int MatT(int &n)
{
int r=1,t;reg int i,j,k;
for(i=1;i<n;++i)
{
for(j=i+1;j<n;++j)while(K[j][i])
{
t=K[i][i]/K[j][i];
if(t)for(k=i;k<n;++k)
K[i][k]=Dec(K[i][k],Mul(K[j][k],t));
swap(K[i],K[j]);r=Dec(0,r);
}
r=Mul(r,K[i][i]);if(!r) return r;
}
return r;
}
int N,M,fa[MN],re[MN],tt,st[MN],ans,ff[MN];
int getf(int *f,int x){return f[x]==x?x:f[x]=getf(f,f[x]);}
void union_(int *f,int x,int y){x=getf(f,x);y=getf(f,y);if(x!=y)f[y]=x;}
struct edge{int x,y,w;}e[ME];
bool cmp(edge x,edge y){return x.w<y.w;}
vector<int>G[MN];
void ins(int x,int y){++K[x][x],++K[y][y],K[x][y]=Dec(K[x][y],1),K[y][x]=Dec(K[y][x],1);}
int main()
{
freopen("crazy.in","r",stdin);
freopen("crazy.out","w",stdout);
N=read(),M=read();
reg int l,r,i,j,x,y;
for(i=1;i<=N;++i)fa[i]=ff[i]=i;
for(i=1;i<=M;++i)e[i].x=read(),e[i].y=read(),e[i].w=read();
std::sort(e+1,e+M+1,cmp);
for(ans=l=1,r=0;l<=M;++l)
{
while(e[r+1].w==e[l].w)++r;
for(tt=0,i=l;i<=r;++i)
{
x=getf(fa,e[i].x);y=getf(fa,e[i].y);if(x==y)continue;
if(!re[x])re[x]=++tt,st[tt]=x;x=re[x];
if(!re[y])re[y]=++tt,st[tt]=y;y=re[y];
ins(x,y);union_(ff,x,y);
}
if(!tt)continue;
for(j=getf(ff,1),i=1;i<=tt;++i)if(getf(ff,i)==i&&ff[i]!=j)ins(j,i);
ans=Mul(ans,MatT(tt));
for(i=1;i<=tt;++i)re[st[i]]=0;
for(i=1;i<=tt;++i)ff[i]=i;
for(i=1;i<=tt;++i)for(j=1;j<=tt;++j)K[i][j]=0;
for(i=l;i<=r;++i)union_(fa,e[i].x,e[i].y);l=r;
}
for(i=1,j=0;i<=N;++i)j+=i==getf(fa,i);
if(j>1)printf("0
");else printf("%d
",ans);
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!