今天做完了POJ的第1330题,AC之后发现性能也不错,特把思路重新捋一遍,把结果与大家分享。
一、题意解析
输入为一颗树的结点数及其每一条边的连线。要求输出给定两个结点的最近公共祖先编号。
二、结题思路
之前刚刚做了POJ的1183题,其实本题要比1183简单许多。由于每一行输入指定唯一的一条边且第一个结点为第二个结点的父亲结点。所以可定义数组(a),用来保存每个结点的父结点编号。此时,a[x]为编号为x的结点的父节点的编号。则循环令x=a[x]可求出x的所有祖先,此时求最近公共祖先便为求出两个结点最先共有的一个x。具体步骤为:首先分别计算出x与y的在树中的“层数”,层数=祖先数+。则本题目的变为从低层到高层(根节点)方向求在一层中的结点是否相同。
其实自己感觉也没有太说清楚。也没有花太多时间,只是想把自己做的不错的结果与大家分享下。
三、AC代码
#include <stdio.h>
#include <string.h>
#define N 10001
int a[N] = {0}; //Record the parent of each node.
void build_tree(int x, int y)
{
a[y] = x;
}
int check_anc(int x, int count)
{
int anc;
anc = a[x];
count++;
if(anc != 0)
check_anc(anc,count);
else
return count;
}
int find_anc(int x, int y, int count_x, int count_y)
{
int dif = count_x - count_y;
int temp, i, temp1, temp2;
if(dif > 0)
{
temp1 = x;
temp2 = y;
}
else
{
dif = 0 - dif;
temp1 = y;
temp2 = x;
}
for(i = 0; i < dif; i++)
temp1 = a[temp1];
while(temp1 != 0)
{
if(temp1 == temp2)
break;
temp1 = a[temp1];
temp2 = a[temp2];
}
return temp1;
}
int judge_node(int x, int y)
{
int anc_x, anc_y;
int count_x, count_y;
count_x = check_anc(x,0);
count_y = check_anc(y,0);
int result = find_anc(x,y,count_x,count_y);
}
int main()
{
int i,n,x,y,res;
scanf("%d",&i);
for(; i > 0; i--) //For each tree.
{
scanf("%d",&n);
for(; n > 1; n--)
{
scanf("%d%d",&x,&y);
build_tree(x,y);
}
scanf("%d%d",&x,&y);
res = judge_node(x,y);
printf("%d\n",res);
memset(a,0,N*4);
}
return 0;
}