"Concurso de algoritmos · 300 preguntas rápidas" Una pregunta por día: "x1 == x2"

" 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.


" 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")

Supongo que te gusta

Origin blog.csdn.net/weixin_43914593/article/details/132598214
Recomendado
Clasificación