Codeforces Round #548 (Div. 2)1139C dsu on tree树上的启发式合并

n=1e5 k=100
0红 1黑
至少经过1次黑边 反面全为红边 红边点并查集合并记录最大长度 排除单点为1
注意减法取模 要加mod

ll pow_mod(ll a,ll b,ll mod)
{
	ll res=1;
	while(b!=0)
	{
		if(b&1)
			res=res*a%mod;
		b>>=1;
		a=a*a%mod;
	}
	return res;
}
int pre[maxn],vis[maxn],size[maxn];//1e5根节点点是否被访问 
int find(int x)
{
	while(x!=pre[x])
		x=pre[x];
	return x;
}
void join(int x,int y)
{
	int rx=find(x);
	int ry=find(y);
	if(rx!=ry)//连通红色除根外 大小清0 就算未被访问0^k=0 
	{
		pre[rx]=ry;
		size[ry]+=size[rx];
		size[rx]=0;
	}
}
int main()
{
	IO;
	int n,k;
	//n^k=1e5^100 排除连通红色 和 单点为1
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		pre[i]=i;
		size[i]=1;
	}
	int u,v,x;
	for(int i=1;i<=n-1;i++)
	{
		
		cin>>u>>v>>x;
		if(x==0)
			join(u,v); 
	}
	ll sum=0;
	for(int i=1;i<=n;i++)
	{
		if(vis[find(i)]==0)
		{
			vis[find(i)]=1;
			sum=(sum+pow_mod(size[find(i)],k,mod))%mod;
		}
	}

	ll ans=(pow_mod(n,k,mod)-sum+mod)%mod;//注意减法取模 
	cout<<ans<<endl;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_40423146/article/details/88925540