/******************************************************************************************************
** Copyright (C) 2011.05.01 - 2013.07.01
** Author: famousDT <13730828587@163.com>
** Edit date: 2011-04-23
******************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>//abs,atof(string to float),atoi,atol,atoll
#include <math.h>//atan,acos,asin,atan2(a,b)(a/b atan),ceil,floor,cos,exp(x)(e^x),fabs,log(for E),log10
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <string.h>//memcpy(to,from,count
#include <ctype.h>//character process:isalpha,isdigit,islower,tolower,isblank,iscntrl,isprint
#include <algorithm>
using namespace std;
//typedef long long int ll;
#define PI acos(-1)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MALLOC(n, type) ((type *)malloc((n) * sizeof(type)))
#define FABS(a) ((a) >= 0 ? (a) : (-(a)))
/***********************************************解题思路***************************************
**将LCA问题转化为RMQ
**http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor
**********************************************************************************************/
struct node
{
int parent; //父亲
int position; //RMQ表位置
vector<int> child;
};
vector<node> tree;
//分别用于存储RQM的遍例次序和深度
vector<int> order, depth;
//由树建立RQM表,递归方式
void build_RMQ_table(int nod, int dep)
{
//进入当前节点,存储其编号和深度
order.push_back(nod);
depth.push_back(dep);
node &n = tree[nod];
//第一次遍例该节点,记录节点在表中的位置
n.position = n.position == -1 ? (order.size() - 1) : n.position;
//多叉树的标准深度遍例方式,依次访问所有子节点
vector<int>::iterator iter;
for (iter = n.child.begin(); iter != n.child.end();) {
build_RMQ_table(*iter++, dep + 1);
order.push_back(nod);
depth.push_back(dep);
}
}
int main()
{
map<string, int> nametable;
nametable.clear();
//新节点的初始值,父为-1,RMQ表位置为-1
node newnode;
newnode.parent = newnode.position = -1;
string c, p;
string s1, s2;
vector<node>::iterator iter;
nametable.clear();
tree.clear();
while (cin>>c>>p && c != "no.child") {
if (nametable.end() == nametable.find(p)) {
nametable[p] = tree.size();
tree.push_back(newnode);
}
if (nametable.end() == nametable.find(c)) {
nametable[c] = tree.size();
tree.push_back(newnode);
}
//建立父子关系
tree[nametable[p]].child.push_back(nametable[c]);
tree[nametable[c]].parent = nametable[p];
}
//如果存在森林,简历虚拟的总跟,放在列表最后
tree.push_back(newnode);
//遍历所有节点
for (iter = tree.begin(); iter != tree.end() - 1; ++iter) {
if (iter->parent == -1) {//没有父亲的节点放到总节点儿子列表
iter->parent = tree.size() - 1;
tree.back().child.push_back(iter - tree.begin());
}
}
//从总跟开始地鬼简历RMQ表
build_RMQ_table(tree.size() - 1, 0);
while (cin>>s1>>s2) {
map<string, int>::iterator i1 = nametable.find(s1);
map<string, int>::iterator i2 = nametable.find(s2);
if (i1 == nametable.end() || i2 == nametable.end()) {
cout << "no relation" << endl;
continue;
}
int n1 = tree[i1->second].position;
int n2 = tree[i2->second].position;
if (depth[n1] > depth[n2]) {
swap(n1, n2);
}
//RMQ查询
vector<int>::iterator itertmp = min_element(depth.begin() + MIN(n1, n2),
depth.begin() + MAX(n1, n2) + 1);
//如果最小共同祖先(LCS)为总根,认为无关
if (tree[order[itertmp - depth.begin()]].parent == -1) {
cout << "no relation" << endl;
continue;
}
int removed = depth[n2] - depth[n1];
int cousin = depth[n1] - *itertmp;
//二者有一个人是LCS
if (cousin == 0) {
for (; removed > 2; --removed) {
cout << "great ";
}
if (removed > 1)
cout << "grand ";
cout << (tree[i1->second].position == n1 ? "parent" : "child") << endl;
}
else if (cousin == 1 && removed == 0)
cout << "sibling" << endl;
else {
cout << cousin - 1 << " cousin";
if (removed > 0) {
cout << " removed " << removed;
}
cout << endl;
}
}
return 0;
}
SOJ-1008(将LCA问题转化为RMQ)
最新推荐文章于 2017-08-11 09:27:00 发布