【bzoj1016】[JSOI2008]最小生成树计数

题目:

我是超链接

题解:

最小生成树三定理

并查集不能压缩路径,因为这样回溯时就不能直接还原了

代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define Mod 31011
using namespace std;
struct hh
{
	int a,b,c;
}no[1005],pm[1005];
int f[105],hs,qz[1005],n,m,xz[1005];
int cmp(hh a,hh b){return a.c<b.c;}
int find(int x)
{
	if (f[x]!=x) return find(f[x]);
	return f[x];
}
void dfs(int zz,int be,int vv)
{
	if (vv>qz[zz]) return; 
	if (be>pm[zz].b)
	{
		if (vv==qz[zz])
		  hs++,hs%=Mod;
		return;
	}
	int x=find(no[be].a),y=find(no[be].b);
    if (x!=y){f[x]=y; xz[be]=1; dfs(zz,be+1,vv+1); xz[be]=0;f[x]=x;}
	dfs(zz,be+1,vv);
}
int main()
{
	int i,maxx=0,zl=0,ans=1,tot=0,j;
	scanf("%d%d",&n,&m);
	for (i=1;i<=m;i++)
	  scanf("%d%d%d",&no[i].a,&no[i].b,&no[i].c);	
	sort(no+1,no+m+1,cmp);
	for (i=1;i<=n;i++) f[i]=i;
    for (i=1;i<=m;i++)
      {
      	if (no[i].c!=no[i-1].c)
          pm[++zl].a=i,pm[zl-1].b=i-1;//起点 
        int x=find(no[i].a),y=find(no[i].b);
    	if (x!=y)
    	  f[x]=y,qz[zl]++,tot++;
      }
    pm[zl].b=m;
	if (tot!=n-1){printf("0");return 0;} 
	for (i=1;i<=n;i++) f[i]=i;
	for (i=1;i<=zl;i++)
	  if (qz[i])
	  {
	  	hs=0;
 	  	dfs(i,pm[i].a,0);
	  	ans=ans*hs%Mod;
	  	for (j=pm[i].a;j<=pm[i].b;j++)//每一种权值连完后效果一样 
	    {
	    	int x=find(no[j].a),y=find(no[j].b);
         	if (x!=y) f[x]=y;
		}
	  }
	printf("%d",ans%Mod);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值