Cod sursa(job #995998)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 10 septembrie 2013 17:49:04
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 3.56 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

class DisjointSets {
  public:
    DisjointSets(const int setSize = 0) {
        this->setSize = setSize;
        father = vector<int>(setSize, NIL);
        rank = vector<int>(setSize, 0);
        size = vector<int>(setSize, 1);
    }

    int Find(const int x) {
        if (father[x] == NIL)
            return x;
        return father[x] = Find(father[x]);
    }

    int Size(const int x) {
        return size[Find(x)];
    }

    bool Merge(int x, int y) {
        x = Find(x);
        y = Find(y);
        if (x == y)
            return false;
        if (rank[x] < rank[y])
            swap(x, y);
        father[y] = x;
        rank[x] = max(rank[x], rank[y] + 1);
        size[x] += size[y];
        return true;
    }

  private:
    static const int NIL = -1;

    int setSize;
    vector<int> father, rank, size;
};

class Tree {
  public:
    Tree(const int V = 0, const int root = 0) {
        this->V = V;
        this->root = root;
        G = vector< vector<int> >(V, vector<int>());
    }

    int Size() const {
        return V;
    }

    vector<int> &Adjacent(const int x) {
        return G[x];
    }

    void AddEdge(const int x, const int y) {
        G[x].push_back(y);
        G[y].push_back(x);
    }

    vector<int> ComputeLCA(const vector< pair<int, int> > &queries) {
        vector< vector< pair<int, int> > > nodeQueries = vector< vector< pair<int, int> > >(V, vector< pair<int, int> >());
        for (int i = 0; i < int(queries.size()); ++i) {
            nodeQueries[queries[i].first].push_back(make_pair(queries[i].second, i));
            nodeQueries[queries[i].second].push_back(make_pair(queries[i].first, i));
        }
        vector<int> answers = vector<int>(int(queries.size()), NIL);
        DisjointSets sets = DisjointSets(V);
        vector<int> ancestors = vector<int>(V, NIL);
        vector<bool> visited = vector<bool>(V, false);
        AncestorDFS(root, visited, nodeQueries, sets, ancestors, answers);
        return answers;
    }

  private:
    static const int NIL = -1;

    int V, root;
    vector< vector<int> > G;

    void AncestorDFS(const int x, vector<bool> &visited, const vector< vector< pair<int, int> > > &queries, DisjointSets &sets, vector<int> &ancestors, vector<int> &answers) {
        visited[x] = true;
        for (const auto &y: G[x]) {
            if (!visited[y]) {
                AncestorDFS(y, visited, queries, sets, ancestors, answers);
                sets.Merge(x, y);
                ancestors[sets.Find(x)] = x;
            }
        }
        for (const auto &q: queries[x])
            if (visited[q.first])
                answers[q.second] = ancestors[sets.Find(q.first)];
    }
};

Tree T;
vector< pair<int, int> > Queries;
vector<int> LCA;

void Solve() {
    LCA = T.ComputeLCA(Queries);
}

void Read() {
    ifstream cin("lca.in");
    int v, q;
    cin >> v >> q;
    T = Tree(v, 0);
    for (int x = 2; x <= v; ++x) {
        int y;
        cin >> y;
        T.AddEdge(x - 1, y - 1);
    }
    Queries = vector< pair<int, int> >(q);
    for (int i = 0; i < q; ++i) {
        cin >> Queries[i].first >> Queries[i].second;
        --Queries[i].first;
        --Queries[i].second;
    }
    cin.close();
}

void Print() {
    ofstream cout("lca.out");
    for (int i = 0; i < int(LCA.size()); ++i)
        cout << LCA[i] + 1 << "\n";
    cout.close();
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}