Pagini recente » Cod sursa (job #1265027) | Cod sursa (job #1070183) | Cod sursa (job #1932008) | Cod sursa (job #2395493) | Cod sursa (job #1741702)
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
InputReader in = new InputReader(new FileInputStream("lca.in"));
int N = in.nextInt();
int M = in.nextInt();
Graph tree = new Graph(N);
for (int i = 2; i <= N; ++i){
int father = in.nextInt();
tree.addEdge(father, i);
}
HeavyPathDecomposition HPD = new HeavyPathDecomposition(tree);
HPD.buildHeavyPaths(1);
StringBuilder output = new StringBuilder();
while (M --> 0){
int x = in.nextInt();
int y = in.nextInt();
output.append(HPD.lca(x, y) + "\n");
}
PrintWriter out = new PrintWriter(new FileOutputStream("lca.out"));
out.print(output);
out.close();
}
static class Graph{
private static class Edge{
int node;
int next;
Edge(int node, int next){
this.node = node;
this.next = next;
}
}
final static int NIL = -1;
private int[] head;
private ArrayList<Edge> graph;
private int N;
private int counter;
Graph(int N){
initialize(N);
}
public int getN() {
return N;
}
private void initialize(final int N){
head = new int[N];
graph = new ArrayList<>();
this.N = N;
this.counter = 0;
Arrays.fill(head, NIL);
}
void addEdge(int x, int y){
assert 1 <= x && x <= N;
x--; y--;
graph.add(new Edge(y, head[x]));
head[x] = counter++;
}
int getHead(int node){
assert 1 <= node && node <= N;
node--;
return head[node];
}
int getNext(int p){
assert 0 <= p && p < counter;
return graph.get(p).next;
}
int getNeighbour(int p){
assert 0 <= p && p < counter;
return graph.get(p).node + 1;
}
}
static class HeavyPathDecomposition {
private Graph graph;
private final int N;
private int numberOfPaths;
//private ArrayList<SegmentTree> segmentTrees;
private final int[] size, father, depth;
private final int[] path, lengthPath, posInPath, startNode;
HeavyPathDecomposition(Graph G){
this.graph = G;
this.N = G.getN();
this.numberOfPaths = 0;
//segmentTrees = new ArrayList<>();
size = new int[N + 1];
father = new int[N + 1];
depth = new int[N + 1];
path = new int[N + 1];
lengthPath = new int[N + 1];
posInPath = new int[N + 1];
startNode = new int[N + 1];
}
private void dfs(int node){
size[node] = 1;
int heavySon = 0;
for (int p = graph.getHead(node); p != Graph.NIL; p = graph.getNext(p)) {
int son = graph.getNeighbour(p);
if (father[son] == 0){
father[son] = node;
depth[son] = depth[node] + 1;
dfs(son);
size[node] += size[son];
if (size[heavySon] < size[son])
heavySon = son;
}
}
if (heavySon == 0)
path[node] = numberOfPaths++;
else
path[node] = path[heavySon];
posInPath[node] = lengthPath[path[node]]++;
}
void buildHeavyPaths(int root){
if (!(1 <= root && root <= N)) throw new AssertionError();
father[root] = root;
depth[root] = 0;
dfs(root);
for (int i = 1; i <= N; i++) {
posInPath[i] = lengthPath[path[i]] - posInPath[i] - 1;
if (posInPath[i] == 0)
startNode[path[i]] = i;
}
}
int lca(int x, int y){
if (!(1 <= x && x <= N)) throw new AssertionError();
if (!(1 <= y && y <= N)) throw new AssertionError();
while (path[x] != path[y]){
if (depth[startNode[path[x]]] < depth[startNode[path[y]]])
y = father[startNode[path[y]]];
else
x = father[startNode[path[x]]];
}
return posInPath[x] < posInPath[y] ? x : y;
}
/*void buildSegmentTrees(int[] keys){
int[][] values = new int[numberOfPaths][];
for (int i = 0; i < numberOfPaths; i++)
values[i] = new int[lengthPath[i]];
for (int i = 1; i <= N; i++)
values[path[i]][posInPath[i]] = keys[i];
for (int i = 0; i < numberOfPaths; i++)
segmentTrees.add(new SegmentTree(values[i]));
}
void update(int node, int newKey){
segmentTrees.get(path[node]).update(posInPath[node], newKey);
}
int query(int x, int y){
if (depth[startNode[path[x]]] < depth[startNode[path[y]]]){
int tmp = x;
x = y;
y = tmp;
}
if (path[x] == path[y])
return segmentTrees.get(path[x]).query(Math.min(posInPath[x], posInPath[y]),
Math.max(posInPath[x], posInPath[y]));
else
return Math.max(segmentTrees.get(path[x]).query(0, posInPath[x]),
query(father[startNode[path[x]]], y));
}
*/
}
static class InputReader{
private BufferedReader reader;
private StringTokenizer tokenizer;
InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 1 << 20);
tokenizer = null;
}
private String nextToken() {
while (tokenizer == null || !tokenizer.hasMoreTokens()){
try {
tokenizer = new StringTokenizer(reader.readLine());
}
catch (IOException e){
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
int nextInt() {
return Integer.parseInt(nextToken());
}
String nextString(){
return nextToken();
}
}
}