G. Contar gráficos (búsqueda de unión)

Problema - G - Codeforces

Dado un árbol que consta de n vértices. Un árbol es un gráfico conexo no dirigido y sin ciclos. Cada borde del árbol tiene su peso wi.

Tu tarea es contar el número de formas diferentes que satisfacen las siguientes cuatro condiciones:

 
 

Texto sin formato

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

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

Dos gráficos se consideran diferentes si sus conjuntos de aristas son diferentes, teniendo en cuenta los pesos de las aristas.

La respuesta puede ser muy grande, tome el módulo de 998244353 y envíelo.

ingresar:

La primera línea contiene un número entero t (1≤t≤104), que indica el número de casos de prueba.

La primera línea de cada caso de prueba contiene dos números enteros n y S (2≤n≤2⋅105, 1≤S≤109), que indican el número de vértices y el límite superior del peso.

Las siguientes n-1 líneas describen los bordes del árbol. La i-ésima línea contiene tres números enteros ui, vi y wi (1≤ui, vi≤n, ui≠vi, 1≤wi≤S), lo que indica un peso wi. lado.

Asegúrese de que la suma de n en todos los casos de prueba no exceda 2⋅105.

Producción:

Para cada caso de prueba, genere la cantidad de gráficos diferentes que cumplan las condiciones y genere el módulo 998244353.

Ejemplo

Aporte

Copiar

 
 

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

Producción

Copiar

1 
8 
80 
650867886

Solución:
dado que es un árbol de expansión mínima, piense en el algoritmo relacionado con el árbol de expansión mínima. Kruskal usa la búsqueda de unión para vincular dos puntos que no están en el mismo conjunto cada vez, y eventualmente conecta todo el gráfico.

Supongamos que ahora tenemos dos conjuntos s1 y s2 que no están en el mismo conjunto. Necesitamos como máximo s1*s2 - 1 enlace de arista. ¿Por qué reducirlo en uno porque no puede haber aristas duplicadas? ¿Cuál es el rango de valores x de estas aristas? ? Debería ser w < x <= s

Cada borde tiene situaciones s - w, pero tampoco podemos conectar nada, así que agregue una situación como s - w + 1

Cada borde puede ser así.

El número de casos es (s - w + 1)^(s1*s2 - 1) casos. Cada vez que se vinculen dos conjuntos no conectados, será así, así que multiplique

#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();
	}
}

Supongo que te gusta

Origin blog.csdn.net/m0_64158084/article/details/132977302
Recomendado
Clasificación