1. 程式人生 > >求最近祖先和最近祖先樹所含節點個數問題--三星研究院

求最近祖先和最近祖先樹所含節點個數問題--三星研究院

You are to find the closest common ancestor of two vertices in a binary tree. For example, the common ancestors of vertices 8 and 13 in the figure below are vertices 3 and 1. Among them, vertex 3 is the closest to the vertex 8 and 13. And the size of sub-tree (the number of vertices in the sub-tree) rooted by vertex 3 is 8.

Given a binary tree and two vertices, write a program that finds the closest common ancestor and computes the size of the sub-tree rooted by the closest common ancestor. No input is given where one of the two given vertices is an ancestor of the other. For example, ‘11 and 3’ in the above tree is an invalid input. Therefore, your program does not have to consider this case.

 

[Constraints]

The number of vertices are from 3 to 10000

 

 

[Input]

You are given 10 test cases. Each test case has two lines, so the total number of lines is 20. In each test case, the first line consists of four integers, V (the number of vertices in the tree), E (the number of edges), and the indices of two vertices. E edges are listed in the next line. Each edge is represented by two vertices; the index of the parent vertex always precedes the index of the child. For example, the edge connecting vertices 5 and 8 is represented by “5 8”, not by “8 5.” There is no order in which the edges are given. Every consecutive integer in the input is separated by a space. 

 

  

Given 10 test cases,

First 4 test cases contain small number of vertices(3, 5, 7, 10 each).

Next 6 test cases contain same or greater than 50 vertices.

 

 

The indices of vertices are integers from 1 to V, and root vertex always has the index 1.

It is guaranteed that the parent vertex has smaller index than the child vertex.

In this problem, it is not important whether the child is the left child of the parent or the right child; so you can decide this arbitrarily.

 

 

[Output]

Output 10 answers in 10 lines. Each line starts with ‘#x’ meaning the index of a test case, and writes the answer after a space. The answer has two integers: the index of the closest common ancestor and the size of the sub-tree rooted by the closest common ancestor. These two integers are separated by a space as well. 

 

   

[I/O Example]

Input (20 lines in total)

13 12 8 13 Start of the first input

1 2 1 3 2 4 3 5 3 6 4 7 7 12 5 9 5 8 6 10 6 11 11 13

10 9 1 10 Start of the second input

1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10

...

Output (10 lines in total)

#1 3 8

#2 1 10

...

 

#include <stdio.h>
#include <math.h>

int i=0,j=0;

int main()
{
    
 int ac,N,edge,nod1,nod2;#ac最近祖先節點編號
 int buildb(int a[],int b[][5],int N,int edge);//重構陣列,儲存b陣列第0-3列。0該節點,1左孩子,2右孩子 3 父節點
 int high(int b[][5],int t);//求節點高度
 int conod(int b[][5],int t);//求以t為根的樹所含的節點數量。
 int find(int b[][5],int nod1,int nod2);//找出最近祖先節點編號
 
 
 for(j=0; j<10;j++ ){
    scanf("%d %d %d %d\n",&N,&edge,&nod1,&nod2);
    int a[edge*2],b[N+1][5];//0該節點,1左孩子,2右孩子 3 父節點 4節點高度
    
    for(i = 0;i<edge;i++){
    	
    	scanf("%d %d ",&a[i*2],&a[1+i*2]);
     }
     scanf("\n");
     
    buildb(a,b,N,edge); 
    
    for(i = 1;i<N+1;i++){
        //printf("%d %d %d %d",b[i][0],b[i][1],b[i][2],b[i][3]);
        b[i][4] = high(b,i);
    }
    
    ac = find(b,nod1,nod2);
    printf("#%d %d %d\n",j+1,ac,conod(b,ac));
    
 }
 
 return 0;
}


int buildb(int a[],int b[][5],int N,int edge){
    
    
    for(i=0;i<N+1;i++){
        b[i][0] = i;b[i][1]=0;b[i][2]=0;b[i][3]=0;b[i][4]=0;
    }
    for(i=0;i<edge;i++){
        if(b[a[i*2]][1] == 0)
           b[a[i*2]][1] = a[i*2+1];
        else{
            b[a[i*2]][2] = a[i*2+1];
        }
        b[a[i*2+1]][3] = a[i*2];
        
    }
   
}


int high(int b[][5],int t){//遞迴 獲取層數 
    if(t==1&t==0)
        return 1;
        
    else
        return high(b,b[t][3])+1;
}

int conod(int b[][5],int t){
    if(b[t][1]==0&b[t][2]==0){
        return 1;
    }
    else if(b[t][2]==0){
        return conod(b,b[t][1])+1;
    }
    else
       return conod(b,b[t][1])+conod(b,b[t][2])+1; 
}

int find(int b[][5],int nod1,int nod2){
    int n;
    n = b[nod1][4] - b[nod2][4];
    if(n < 0){
        n = -n;
        for(i = 0;i < n;i++){
            nod2 = b[nod2][3];
        }
        
    }
    else{
        for(i = 0;i < n;i++){
            nod1 = b[nod1][3];
        }
    }
    for(i = b[nod1][4];i > 0;i--){
        if(nod1 == nod2)
            return nod1;
        else{
            nod1 = b[nod1][3];
            nod2 = b[nod2][3];
        }
    }      
}


還有個bug沒解決。。。

 

 

記憶體訪問錯誤問題。