Codeforces Ronda # 670 (Div.2) C. Centroides de corte de enlace (árbol transversal dfs, centroide)

C. Centroides de corte de enlace

C.
Significado de la pregunta de Link Cut Centroids : dado un árbol de n nodos, suponga que entre los n nodos, si se elimina uno de los nodos k (incluidos todos los bordes contenidos en el nodo), el punto más grande contenido en cada bloque conectado El número de es el más pequeño, entonces el nodo k es el centroide del árbol.
Ahora hay dos operaciones

  1. Seleccione dos nodos a 1, a 2 a_1, a_2una1Un2Y borra el borde entre los dos
  2. Seleccione dos nodos a 1, a 2 a_1, a_2una1,una2Conectar los dos puntos
    requiere que el centroide del árbol sea único después de dos operaciones.

Idea:
observe atentamente el gráfico con dos centroides que se dan en el título:
Los puntos 1, 2 son los dos centroides de esta imagen.

Luego haz algunas fotos a mano, puedes encontrar

  1. Solo dos centroides como máximo
  2. Si hay 2 centroides, entonces el árbol debe tener simetría.
  3. Si hay dos centroides, no debe haber otros puntos entre ellos (porque son simétricos. Si hay un número impar de puntos en el medio, entonces el centro de masa es el centro de masa; si hay un número par de puntos en el medio, empuje hacia el centro adyacente El punto es el centroide),
    entonces el código general es relativamente simple
  • Tome el nodo 1 como raíz, dfs atraviesa el árbol, cuenta el número de hijos de cada punto (incluido él mismo) y lo registra en hijo [] hijo []s o n [ ] array, registrar el nodo padref [] F []al mismo tiempof [ ] (Se utilizan dos juicios en el conteo subsiguiente)
  • Atraviesa todos los n nodos, asumiendo que iiSe eliminan los i nodos, y luego se busca en cada nodo adyacente el número de nodos en el bloque conectado donde se encuentran:
    • Nodo padre = n - hijo [i] n-hijo [i]norte-s o n [ i ]
    • Hijo nodo kkk= s o n [ k ] son[k] s o n [ k ]
  • Simplemente tome el valor máximo y luego haga una estructura cun [] cun []c u n [ ] Registre el número máximo de nodos en el bloque conectado después de eliminarlonum numn u my id desubíndice de nodo propio actuali dsort sorts o r t

Por último, observe el número numérico de los nodos más grandes y segundosSon N u m la misma

  • Igual: hay dos centroides, quita la línea media, e incluso el hijo de uno al otro
  • No es lo mismo: solo hay un centroide, solo encuentra un borde y agrégalo ^^
int f[maxn], son[maxn], co, n, t;
vector<int> G[maxn];
struct node {
    
    
	int num, id;
}cun[maxn];
bool cmp(node a, node b) {
    
    
	return a.num < b.num;
};
int dfs(int fa, int nw) {
    
    
	f[nw] = fa;
	int sum = 1;
	for (int i = 0; i < G[nw].size(); i++) {
    
    
		if (G[nw][i] == fa)continue;
		sum += dfs(nw, G[nw][i]);
	}
	return son[nw] = sum;
}
int main()
{
    
    
	cin >> t;
	int u, v;
	while (t--)
	{
    
    
		cin >> n;
		for (int i = 1; i <= n; i++)G[i].clear();
		co = 0;
		for (int i = 1; i < n; i++) {
    
    
			cin >> u >> v;
			G[u].push_back(v);
			G[v].push_back(u);
		}
		dfs(0, 1);
		int maxx;
		for (int i = 1; i <= n; i++) {
    
    
			maxx = 0;
			for (int j = 0; j < G[i].size(); j++) {
    
    
				if (G[i][j] == f[i]) {
    
    
					maxx = max(maxx, n - son[i]);
				}
				else {
    
    
					maxx = max(maxx, son[G[i][j]]);
				}
			}
			cun[++co].id = i;
			cun[co].num = maxx;
		}
		sort(cun + 1, cun + 1 + n, cmp);
		int ans;
		if (cun[1].num == cun[2].num) {
    
    
			for (int i = 0; i < G[cun[1].id].size(); i++) {
    
    
				ans = G[cun[1].id][i];
				if (G[cun[1].id][i] != cun[2].id)break;
			}
			cout << cun[1].id << " " << ans << endl;
			cout << ans << " " << cun[2].id << endl;
		}
		else {
    
    
			ans = G[cun[1].id][0];
			cout << cun[1].id << " " << ans << endl;
			cout << cun[1].id << " " << ans << endl;
		}
	}
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_44986601/article/details/108674117
Recomendado
Clasificación