AcWing4202 Ir a través del círculo (ruta más corta en el árbol / fuerza bruta de optimización de conjunto de bits)

Enlace temático: A través del círculo

Idea general

dado _n puntos,mmm círculosSe garantiza que cada punto no estará en el borde del círculo, y que el círculo y el círculo no se intersecan.

tener kk tiempos de consulta, cada consulta conecta dos puntosa, ba, bun ,b , al menos cuántos círculos deben pasar.

Ideas para resolver problemas

Idea 1: Convertir al problema del camino más corto en el árbol

Consideramos que debido a que el título garantiza que el círculo y el círculo no se cortan, y el punto no está en el círculo, entonces si configuro el conjunto completo para que sea m + 1 m + 1metro+1 círculo, luegonnn puntos deben estar todos contenidos enm + 1 m+1metro+1 circulo

Si consideramos algún punto ppLa circunferencia a la que pertenece p es: contiene el punto ppp , y el radio más pequeñoEntonces cada punto también debe tener uncírculo al que pertenece.

Consideramos pedir dos puntos a, ba, b cada vezun ,b :
① Jovena, ba, bun ,b está en el mismo círculo, la respuesta es0 00.
② Joven,ba, bun ,b no está en el mismo círculo, entonces partimos de los puntosa, ba, bun ,b inicia la línea, pasando solo por el puntoaaa o puntobbborde redondeado de b hasta que se encuentre el primero que contienea, ba, bun ,Cuando el círculo de b está conectado con dos líneas, debería ser la solución óptima en este momento.

Encontramos que ② es muy similar al concepto del ancestro común más cercano en un árbol Si el problema se abstrae a un árbol, es equivalente a buscar un peso de borde de 1 1El camino más corto de dos puntos cualquiera en el árbol de 1. Podemos resolverlo por la diferencia en el árbol.


Idea 2: optimizar la violencia

Mediante el análisis de la idea 1, podemos sacar la conclusión: Para que los puntos a, ba, b estén conectadosun ,segundo 穿过最少圆的数量 = 仅包含点a的圆数量 + 仅包含点b的圆数量 _

Pero considerando que hay 1 0 5 10^51 05 consultas,1 0 3 10^31 03 círculos, nuestra complejidad de tiempo alcanza1 0 8 10^81 08 , difícil en0.3s 0.3stranscurrido dentro del límite de tiempo de 0,3 s .

Observamos la esencia del problema: necesitamos obtener una no esta enbbb , enbbb ausenteaaUn conjunto, que es esencialmente unaXORpara un conjunto, podemos pasarbitset bitsetB i t s e t implementación optimizada.

➡️Si no conoce el problema del conjunto de optimización de conjuntos de bits, puede hacer este problema primero⬅️

código de CA

Convertir a la ruta más corta en el árbol

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E3 + 10;
pair<int, int> p[N];
struct node {
    
     int x, y, r; } cir[N];
int in[N];

bool fact(const pair<int, int> a, const node& b) {
    
    
	int x1 = a.first, y1 = a.second;
	int x2 = b.x, y2 = b.y; int r = b.r;
	int x = x1 - x2, y = y1 - y2;
	return 1ll * x * x + 1ll * y * y <= 1ll * r * r;
}

vector<int> edge[N];
/* 倍增求LCA模版 */
namespace LCA {
    
    
	const int B = 10; // 记录真实的B, f数组多开1即可
	int dep[N], f[N][B + 1];
	void dfs(int x = 1, int fa = 0) {
    
    
		dep[x] = dep[fa] + 1;
		f[x][0] = fa;
		rep(i, B) f[x][i] = f[f[x][i - 1]][i - 1];
		for (auto& to : edge[x]) if (to != fa) dfs(to, x);
	}
	int lca(int x, int y) {
    
    
		if (dep[x] < dep[y]) swap(x, y);
		for (int i = B; i >= 0; --i) if (dep[f[x][i]] >= dep[y]) x = f[x][i];
		if (x == y) return x;
		for (int i = B; i >= 0; --i) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
		return f[x][0];
	}
}
int main()
{
    
    
	int n, m, k; cin >> n >> m >> k;
	rep(i, n) {
    
    
		int x, y; scanf("%d %d", &x, &y);
		p[i] = {
    
     x, y };
	}
	rep(i, m) {
    
    
		int r, x, y; scanf("%d %d %d", &r, &x, &y);
		cir[i] = {
    
     x, y, r };
	}

	rep(i, n) {
    
    
		rep(j, m) {
    
    
			if (fact(p[i], cir[j])) {
    
    
				if (!in[i] or cir[in[i]].r > cir[j].r) in[i] = j;
			}
		}
		if (!in[i]) in[i] = m + 1;
	}

	rep(i, m) {
    
    
		int index = 0;
		rep(j, m) {
    
    
			if (cir[j].r > cir[i].r and fact({
    
     cir[i].x, cir[i].y }, cir[j])) {
    
    
				if (!index or cir[index].r > cir[j].r) index = j;
			}
		}
		if (!index) index = m + 1;
		edge[index].push_back(i), edge[i].push_back(index);
	}

	LCA::dfs();

	rep(i, k) {
    
    
		int a, b; scanf("%d %d", &a, &b);
		a = in[a], b = in[b];
		int lca = LCA::lca(a, b);
		int res = LCA::dep[a] + LCA::dep[b] - 2 * LCA::dep[lca];
		printf("%d\n", res);
	}

	return 0;
}

bitset optimiza la violencia

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E3 + 10;
pair<int, int> p[N];
bitset<N> bt[N];
struct node {
    
     int x, y, r; }cir[N];

bool fact(const pair<int, int>& a, const node& b) {
    
    
	int x1 = a.first, y1 = a.second;
	int x2 = b.x, y2 = b.y;
	int x = x1 - x2, y = y1 - y2;
	return sqrt(1ll * x * x + 1ll * y * y) < b.r;
}
int main()
{
    
    
	int n, m, k; cin >> n >> m >> k;
	rep(i, n) {
    
    
		int x, y; scanf("%d %d", &x, &y);
		p[i] = {
    
     x, y };
	}
	rep(i, m) {
    
    
		int r, x, y; scanf("%d %d %d", &r, &x, &y);
		cir[i] = {
    
     x, y, r };
	}

	rep(i, n) rep(j, m) {
    
    
        bt[i][j] = fact(p[i], cir[j]);
    }

	rep(i, k) {
    
    
		int a, b; scanf("%d %d", &a, &b);
		printf("%d\n", (bt[a] ^ bt[b]).count());
	}

    return 0;
}

FIN

Supongo que te gusta

Origin blog.csdn.net/weixin_45799835/article/details/122252217
Recomendado
Clasificación