" Competencia de algoritmos: 300 preguntas rápidas " se publicará en 2024 y es un libro de ejercicios auxiliar para la "Competencia de algoritmos" .
Todas las preguntas se colocan en el nuevo juez en línea del DO de creación propia .
Los códigos se proporcionan en tres lenguajes: C/C++, Java y Python. Los temas son principalmente temas de nivel medio a bajo y son adecuados para estudiantes principiantes y avanzados.
Directorio de artículos
" x1 == x2 ", enlace: http://oj.ecustacm.cn/problem.php?id=1725
Descripción de la pregunta
[Descripción del problema] Ahora, dadas las restricciones de igualdad o desigualdad de algunas variables, juzgue si estas restricciones pueden satisfacerse al mismo tiempo.
Al ingresar, las variables son x1, x2,...,xn, todas comenzando con x, seguidas del número correspondiente a la variable.
Las restricciones son sólo "=" o "!=".
[Formato de entrada] La primera línea de entrada es un número entero positivo T, lo que indica que hay T conjuntos de datos de prueba. (T≤10)
La primera línea de cada conjunto de datos de prueba es un número entero positivo n, que indica el número de restricciones. (n≤1000000)
En las siguientes n líneas, cada línea genera
xi = xj
xi != xj
donde i y j representan los números de las variables correspondientes. (1≤i,j≤10^9)
[Formato de salida] Para cada conjunto de datos de prueba, genere una fila de Sí para indicar que se puede satisfacer y una fila de No para indicar que no se puede satisfacer.
【Muestra de entrada】
2
4
x1 = x7
x9 != x7
x13 = x9
x1 = x13
2
x1 = x2
x2 = x1
【Muestra de salida】
No
Yes
respuesta
La solución a este problema es, obviamente, fusionar los conjuntos. Primero cree un conjunto de búsqueda de unión y combine restricciones iguales. Luego verifique las restricciones desiguales una por una. Si hay un conflicto con el conjunto de búsqueda de unión, genere "No"; si no hay ningún conflicto, genere "Sí".
Sin embargo, si usa directamente el número de x para crear y buscar, excederá la memoria. Porque el número máximo es 1 0 9 10^91 09 , crea y busca directamente el conjunto, que requiere1 0 9 10^91 09 = 1G de espacio.
¿Cómo optimizar el espacio? Dado que solo hay n=1 0 6 10^61 06 restricciones, el número de x números es solo2 × 1 0 6 2 × 10^62×1 06 . Esta es una discretización típica. El valor original de x es1 0 9 10^91 09 números, convertidos a2 × 1 0 6 2 × 10^62×1 06 nuevos números.
[Punto clave]Discretización.
código C ++
Codificación de discretización (para discretización, consulte "Competencia de algoritmos", Tsinghua University Press, escrito por Luo Yongjun y Guo Weibin, página 75, 2.7 Discretización ), puede codificarla manualmente o puede usar lower_bound() y Unique() de STL. El siguiente código está implementado en STL.
Preste atención al procesamiento de entrada.
#include<bits/stdc++.h>
using namespace std;
struct node{
int x, y, z;}a[1000010];
int tot, b[2000010];
int s[2000010]; //并查集
int get_id(int x){
//返回离散化后的新值
return lower_bound(b + 1, b + 1 + tot, x) - b;
}
int find_set(int x){
if(x != s[x]) s[x] = find_set(s[x]);
return s[x];
}
int main(){
int T; cin >> T;
while(T--) {
int n; cin >> n;
tot = 0;
for(int i = 1; i <= n; i++) {
char ch1, ch2; string str;
cin >> ch1 >> a[i].x >> str >> ch2 >> a[i].y;
if(str[0] == '=') a[i].z = 1; //相等
else a[i].z = 0; //不等
b[++tot] = a[i].x; //把a的编号记录在b中
b[++tot] = a[i].y;
}
sort(b + 1, b + 1 + tot);
tot = unique(b + 1, b + 1 + tot) - (b + 1); //b去重,留下唯一的编号
for(int i = 1; i <= tot; i++) s[i] = i; //建立并查集
for(int i = 1; i <= n; i++)
if(a[i].z) {
//处理相等约束,对离散化后的新编号合并并查集
int sx = find_set(get_id(a[i].x));
int sy = find_set(get_id(a[i].y));
s[sx] = sy;
}
bool ok = true;
for(int i = 1; i <= n; i++)
if(!a[i].z) {
//检查不等约束是否造成矛盾
int sx = find_set(get_id(a[i].x));
int sy = find_set(get_id(a[i].y));
if( sx == sy ){
ok = false;
break;
}
}
if(ok) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
código java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
class Main {
static class Node {
int x, y, z;
Node(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
}
static Node[] a = new Node[1000010];
static int tot;
static int[] b = new int[2000010];
static int[] s = new int[2000010];
static int get_id(int x) {
return Arrays.binarySearch(b, 1, tot + 1, x);
}
static int find_set(int x) {
if (x != s[x]) s[x] = find_set(s[x]);
return s[x];
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
while (T-- > 0) {
int n = Integer.parseInt(br.readLine());
tot = 0;
for (int i = 1; i <= n; i++) {
String str = br.readLine();
int x = 0, y = 0;
if (str.contains("!")) {
String[] split = str.split(" != ");
x = Integer.parseInt(split[0].substring(1));
y = Integer.parseInt(split[1].substring(1));
a[i] = new Node(x, y, 0);
} else {
String[] split = str.split(" = ");
x = Integer.parseInt(split[0].substring(1));
y = Integer.parseInt(split[1].substring(1));
a[i] = new Node(x, y, 1);
}
b[++tot] = a[i].x;
b[++tot] = a[i].y;
}
Arrays.sort(b, 1, tot + 1);
tot = deduplicate(b, tot);
for (int i = 1; i <= tot; i++) s[i] = i;
for (int i = 1; i <= n; i++) {
if (a[i].z == 1) {
int sx = find_set(get_id(a[i].x));
int sy = find_set(get_id(a[i].y));
s[sx] = sy;
}
}
boolean ok = true;
for (int i = 1; i <= n; i++) {
if (a[i].z == 0) {
int sx = find_set(get_id(a[i].x));
int sy = find_set(get_id(a[i].y));
if (sx == sy) {
ok = false;
break;
}
}
}
if (ok) System.out.println("Yes");
else System.out.println("No");
}
}
static int deduplicate(int[] b, int n) {
// 去重
int p = 1;
for (int i = 2; i <= n; i++)
if (b[i] != b[p])
b[++p] = b[i];
return p;
}
}
código pitón
Utilice bisect.bisect_left() para discretizar y configurar para eliminar duplicados.
#pypy
import sys
sys.setrecursionlimit(10000)
import bisect
input = sys.stdin.readline
def get_id(x): return bisect.bisect_left(b, x)
def find_set(x):
if x != s[x]: s[x] = find_set(s[x])
return s[x]
T = int(input())
for _ in range(T):
n = int(input())
a = []
b = []
for i in range(n):
str = input()
x, y = 0, 0
if "!" in str:
split = str.split(" != ")
x = int(split[0][1:])
y = int(split[1][1:])
a.append([x, y, 0])
else:
split = str.split(" = ")
x = int(split[0][1:])
y = int(split[1][1:])
a.append([x, y, 1])
b.append(a[i][0])
b.append(a[i][1])
b = sorted(set(b))
tot = len(b)
s = [i for i in range(tot)]
for i in range(n):
if a[i][2] == 1:
sx = find_set(get_id(a[i][0]))
sy = find_set(get_id(a[i][1]))
s[sx] = sy
ok = True
for i in range(n):
if a[i][2] == 0:
sx = find_set(get_id(a[i][0]))
sy = find_set(get_id(a[i][1]))
if sx == sy:
ok = False
break
if ok: print("Yes")
else: print("No")