"Algorithm Competition·Quick 300 Questions" One question per day: "x1 == x2"

" Algorithm Competition: 300 Quick Questions " will be published in 2024 and is an auxiliary exercise book for "Algorithm Competition" .
All questions are placed in the self-built OJ New Online Judge .
Codes are given in three languages: C/C++, Java, and Python. The topics are mainly mid- to low-level topics and are suitable for entry-level and advanced students.


" x1 == x2 ", link: http://oj.ecustacm.cn/problem.php?id=1725

Question description

[Problem Description] Now given the constraints of equality or inequality of some variables, please judge whether these constraints can be satisfied at the same time.
   When inputting, the variables are x1, x2,...,xn, all starting with x, followed by the number corresponding to the variable.
   The constraints are only "=" or "!=".
[Input format] The first line of input is a positive integer T, indicating that there are T sets of test data. (T≤10)
   The first line of each set of test data is a positive integer n, indicating the number of constraints. (n≤1000000)
   In the next n lines, each line outputs
   xi = xj
   xi != xj
   where i and j represent the numbers of the corresponding variables. (1≤i,j≤10^9)
[Output format] For each set of test data, output a row of Yes to indicate that it can be satisfied, and output No to indicate that it cannot be satisfied.
【Input sample】

2
4
x1 = x7
x9 != x7
x13 = x9
x1 = x13
2
x1 = x2
x2 = x1

【Output sample】

No
Yes

answer

   The solution to this problem is obviously to merge the sets. First create a union search set and merge equal constraints. Then check the unequal constraints one by one. If there is a conflict with the union-find set, output "No"; if there is no conflict at all, output "Yes".
   However, if you directly use the number of x to create and search, it will exceed the memory. Because the maximum number is 1 0 9 10^9109 , directly create and search the set, which requires1 0 9 10^9109 = 1G of space.
   How to optimize space? Since there is only n=1 0 6 10^6106 constraints, the number of x numbers is only2 × 1 0 6 2 × 10^62×106 . This is a typical discretization. The original value of x is1 0 9 10^9109 numbers, converted to2 × 1 0 6 2 × 10^62×106 new numbers.
[Key point]Discretization.

C++ code

   Discretization coding (for discretization, see "Algorithm Competition", Tsinghua University Press, written by Luo Yongjun and Guo Weibin, page 75, 2.7 Discretization ), you can code it manually, or you can use STL's lower_bound() and unique(). The code below is implemented in STL.
  Pay attention to input processing.

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

Java code

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;
    }
}

Python code

   Use bisect.bisect_left() to discretize and set to remove duplicates.

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

Guess you like

Origin blog.csdn.net/weixin_43914593/article/details/132598214