zoukankan      html  css  js  c++  java
  • [JSOI2008]最小生成树计数

    传送门

    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!

  • 相关阅读:
    Flask上下文管理源码分析 ——(3)
    Flask 快速使用 进阶—— (2)
    HTML-语法
    安装kubenetes-遇到的问题总结
    CentOS7-部署kubernetes
    k8s-部署及介绍
    docker-macvlan网络
    Dom编程-左侧菜单栏设计模型实现
    JavaScript-checkbox标签-隐藏、显示、全选、取消和反选等操作
    docker-Overlay原生网络
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/11777641.html
Copyright © 2011-2022 走看看