Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

หาจำนวนขอบที่สามารถหักในต้นไม้ให้ Bitwise OR ของต้นไม้สองต้นที่ได้เท่ากันใน C++

แนวคิด

สำหรับต้นไม้ที่มี m โหนดและตัวเลขผูกกับทุกโหนด เราสามารถหักขอบไหนขอบหนึ่งได้ ซึ่งจะสร้างต้นไม้ใหม่ 2 ต้น ภารกิจคือนับจำนวนขอบที่ทำให้ Bitwise OR ของโหนดในต้นไม้สองต้นที่เกิดหลังหักขอบนั้นเท่ากัน ค่าของทุกโหนด ≤ 10^6

อินพุต

values[] = {1, 3, 1, 3}
    1
   / | \
  2  3  4

เอาต์พุต

2

ขอบระหว่าง 1 และ 2 สามารถหักได้ Bitwise OR ของต้นไม้สองต้นที่ได้คือ 3
ขอบระหว่าง 1 และ 4 ก็สามารถหักได้เช่นกัน

วิธีการ

ปัญหานี้แก้ได้ด้วย DFS (Depth First Search) เนื่องจากค่าโหนด ≤ 10^6 สามารถแทนได้ด้วย 22 บิตไบนารี Bitwise OR ของค่าโหนดก็แทนได้ด้วย 22 บิต วิธีคือหาจำนวนครั้งที่แต่ละบิตถูกเซ็ตในค่าทั้งหมดของ sub-tree สำหรับแต่ละขอบ ตรวจสอบแต่ละบิต 0 ถึง 21 ว่าจำนวนที่มีบิตเซ็ตเป็นศูนย์ในทั้งสองต้นไม้ที่ได้ หรือมากกว่าศูนย์ในทั้งสองต้น ถ้าเงื่อนไขเป็นจริงสำหรับทุกบิต ขอบนั้นนับในผลลัพธ์

ตัวอย่างโค้ด

// C++ implementation of the approach
#include<bits/stdc++.h>
using namespace std;

int m1[1000], x1[22];
int a1[1000][22];
vector<vector<int>> g;
int ans1 = 0;

// DFS แบบง่าย
void dfs(int u1, int p1) {
    for (int i = 0; i < g[u1].size(); i++) {
        int v1 = g[u1][i];
        if (v1 != p1) {
            dfs(v1, u1);
            // นับจำนวนครั้งแต่ละบิตถูกเซ็ตใน sub-tree ที่รากที่ v
            for (int i = 0; i < 22; i++)
                a1[u1][i] += a1[v1][i];
        }
    }
    // ตรวจสอบแต่ละบิต
    int pp1 = 0;
    for (int i = 0; i < 22; i++) {
        if (!((a1[u1][i] > 0 && x1[i] - a1[u1][i] > 0) || (a1[u1][i] == 0 && x1[i] == 0))) {
            pp1 = 1;
            break;
        }
    }
    if (pp1 == 0)
        ans1++;
}

// Driver code
int main() {
    int n1 = 4;
    g.resize(n1 + 1);
    m1[1] = 1;
    m1[2] = 3;
    m1[3] = 1;
    m1[4] = 3;
    
    // นับบิตเซ็ตในต้นไม้ทั้งหมด
    for (int i = 1; i <= n1; i++) {
        int y1 = m1[i];
        int k1 = 0;
        while (y1 != 0) {
            int p1 = y1 % 2;
            if (p1 == 1) {
                x1[k1]++;
                a1[i][k1]++;
            }
            y1 = y1 / 2;
            k1++;
        }
    }
    
    // เพิ่มขอบ
    g[1].push_back(2); g[2].push_back(1);
    g[1].push_back(3); g[3].push_back(1);
    g[1].push_back(4); g[4].push_back(1);
    
    dfs(1, 0);
    cout << ans1;
}

ผลลัพธ์

2