Cod sursa(job #2560814)

Utilizator CriviCriveanu Bogdan Crivi Data 28 februarie 2020 11:57:28
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.22 kb
#include <bits/stdc++.h>

using namespace std;

ifstream in;
ofstream out;

struct Node{
    int key;
    struct Node *left,*right;
};

Node new_node(int key)
{
    Node *temp = new Node;
    temp->key  = key;
    temp->left  = temp->right = NULL;
    return (*temp);
};

void createNode(int parent[], int i, Node *created[], Node **root)
{
    if(created[i]!=NULL)
        return;
    if(parent[i]==-1)
    {
        *root=created[i];
        return;
    }
    if (created[parent[i]] == NULL)
        createNode(parent, parent[i], created, root);
    Node *p = created[parent[i]];
    
    if (p->left == NULL)
        p->left = created[i];
    
    else
        p->right = created[i];
}



Node *createTree(int parent[], int n)
{
    Node *created[n];
    for (int i=0; i<n; i++)
        created[i] = NULL;
    
    Node *root = NULL;
    
    for (int i=0; i<n; i++)
        createNode(parent, i, created, &root);
    
    return root;
}
struct Node *findLCAUtil(struct Node* root, int n1, int n2, bool &v1, bool &v2)
{
    // Base case
    if (root == NULL) return NULL;
  
    // If either n1 or n2 matches with root's key, report the presence
    // by setting v1 or v2 as true and return root (Note that if a key
    // is ancestor of other, then the ancestor key becomes LCA)
    if (root->key == n1)
    {
        v1 = true;
        return root;
    }
    if (root->key == n2)
    {
        v2 = true;
        return root;
    }
  
    // Look for keys in left and right subtrees
    Node *left_lca  = findLCAUtil(root->left, n1, n2, v1, v2);
    Node *right_lca = findLCAUtil(root->right, n1, n2, v1, v2);
  
    // If both of the above calls return Non-NULL, then one key
    // is present in once subtree and other is present in other,
    // So this node is the LCA
    if (left_lca && right_lca)  return root;
  
    // Otherwise check if left subtree or right subtree is LCA
    return (left_lca != NULL)? left_lca: right_lca;
}
  
// Returns true if key k is present in tree rooted with root
bool find(Node *root, int k)
{
    // Base Case
    if (root == NULL)
        return false;
  
    // If key is present at root, or in left subtree or right subtree,
    // return true;
    if (root->key == k || find(root->left, k) ||  find(root->right, k))
        return true;
  
    // Else return false
    return false;
}
  
// This function returns LCA of n1 and n2 only if both n1 and n2 are present
// in tree, otherwise returns NULL;
Node *findLCA(Node *root, int n1, int n2)
{
    // Initialize n1 and n2 as not visited
    bool v1 = false, v2 = false;
  
    // Find lca of n1 and n2 using the technique discussed above
    Node *lca = findLCAUtil(root, n1, n2, v1, v2);
  
    // Return LCA only if both n1 and n2 are present in tree
    if (v1 && v2 || v1 && find(lca, n2) || v2 && find(lca, n1))
        return lca;
  
    // Else return NULL
    return NULL;
}

int parent[100001],n,m;

Node *created[100001];

int main() {
    
    in.open("lca.in");
    out.open("lca.out");
    
    in>>n>>m;
    parent[1]=-1;
    for(int i=2;i<=n;i++)
    {
        in>>parent[i];
    }
    
    Node *root = createTree(parent, n);
    
    
    for(int i=1;i<=m;i++)
    {
        int n1,n2;
        in>>n1>>n2;
        out<<findLCA(root, n1, n2)->key<<'\n';
    }
    return 0;
}