G. Counting Graphs(Union search)

Problem - G - Codeforces

Given a tree consisting of n vertices. A tree is a connected undirected graph without cycles. Each edge of the tree has its weight wi.

Your task is to count the number of different shapes that satisfy the following four conditions:

 
 

Plain Text

 
 
图形没有自环和多重边。
图形的边上的权重是整数且不超过S。

图形只有一个最小生成树。
图形的最小生成树是给定的树。

Two graphs are considered different if their edge sets are different, taking into account the edge weights.

The answer may be very large, take the modulo of 998244353 and output it.

enter:

The first line contains an integer t (1≤t≤104), indicating the number of test cases.

The first line of each test case contains two integers n and S (2≤n≤2⋅105, 1≤S≤109), indicating the number of vertices and the upper bound of the weight.

The next n-1 lines describe the edges of the tree. The i-th line contains three integers ui, vi and wi (1≤ui, vi≤n, ui≠vi, 1≤wi≤S), indicating a weight wi side.

Ensure that the sum of n in all test cases does not exceed 2⋅105.

Output:

For each test case, output the number of different graphics that meet the conditions, and output it modulo 998244353.

Example

Input

Copy

 
 

4

2 5

1 2 4

4 5

1 2 2

2 3 4

3 4 3

5 6

1 2 3

1 3 2

3 4 6

3 5 1

10 200

1 2 3

2 3 33

3 4 200

1 5 132

5 6 1

5 7 29

7 8 187

7 9 20

7 10 4

Output

Copy

1
8
80
650867886

Solution:
Since it is a minimum spanning tree, think about the algorithm related to the minimum spanning tree. Kruskal uses union search to link two points that are not in the same set each time, eventually making the entire graph connected.

Suppose we now have two sets s1 and s2 that are not in the same set. We need at most s1*s2 - 1 edge link. Why reduce it by one because there cannot be duplicate edges. What is the value range x of these edges? It should be w < x <= s

Each edge has s - w situations, but we can also connect nothing, so add one situation as s - w + 1

Every edge can be like this

The number of cases is, (s - w + 1)^(s1*s2 - 1) cases. Every time two non-connected sets are linked, it will be like this, so multiply

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node
{
	int x,y,w;
}a[200040];
bool cmp(node a,node b)
{
	return a.w < b.w;
}
int f[200040],d[200043];
int find(int x)
{
	if(f[x] == x)
	return f[x];
	return f[x] = find(f[x]);
}
int mod = 998244353;
int qpow(int x,int p)
{
	int ans = 1;
	while(p)
	{
		if(p&1)
		ans = ans*x%mod;
		x = x*x%mod;
		p /= 2;
	}
	return ans;
}
void solve()
{
	int n,s;
	cin >> n >> s;
	for(int i = 1;i < n;i++)
	{
		int x,y,w;
		cin >> x >> y >> w;
		a[i] = {x,y,w};
	}
	for(int i = 1;i <= n;i++)
	{
		f[i] = i;
		d[i] = 1;
	}
	sort(a + 1,a + n,cmp);
	int ans = 1;
	for(int i = 1;i < n;i++)
	{
		int x = find(a[i].x);
		int y = find(a[i].y);
		ans = ans*qpow(s - a[i].w + 1,d[x]*d[y] - 1)%mod;
		f[y] = x;
		d[x] += d[y];
	}
	cout << ans <<"\n";
}
signed main()
{
	int t = 1;
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t--)
	{
		solve();
	}
}

Guess you like

Origin blog.csdn.net/m0_64158084/article/details/132977302