Hdu 4409 Family Name List (LCA 家谱 STL 2012金华网赛)
2014-02-06 19:35
309 查看
题意:给出一个家谱,处理三种操作。
(1)L重新打印家谱,同一代的人按照升序;
(2)b name 输出name的亲兄弟有多少个?
(3)c name1 name2输出name1和name2 的最近公共祖先。
注意(3):如果最近公共祖先是name1或者name2,那么要输出其父亲。(因为自己不能是自己的祖先。。)
(1)L重新打印家谱,同一代的人按照升序;
(2)b name 输出name的亲兄弟有多少个?
(3)c name1 name2输出name1和name2 的最近公共祖先。
注意(3):如果最近公共祖先是name1或者name2,那么要输出其父亲。(因为自己不能是自己的祖先。。)
#pragma warning(disable:4786) #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <map> #include <string> using namespace std; const int N=60005; map<string,int> mp; set<string> st ; int father_id ; //father_id[a]=b:名字前有a个点的人输入id为b int Num_bro ; //记录i的兄弟数 int father ; //记录i的父节点 char data [63]; //记录原始数据 int n,curID; int F ,B ,RMQ[N*3][32]; int ID ; void init () { curID=0; memset(father,0,sizeof(father)); memset(Num_bro,0,sizeof(Num_bro)); mp.clear(); Num_bro[0] = 1; //这里很容易错,注意要初始化 for (int i=0;i<=n;i++) st[i].clear(); } void Input () { int j,Num_dots; for (int i=0;i<n;i++) { string str; scanf("%s",data[i]); Num_dots=0; for (j=0;j<strlen(data[i]);j++) //找点的个数 if (data[i][j] == '.') Num_dots++; else break; father_id[Num_dots]=i; //用来找父子关系 for (;j<strlen(data[i]);j++) //将该名字赋值给临时变量 str+=(data[i][j]); mp[str]=i; //建立映射关系 if (Num_dots) { st[father_id[Num_dots-1]].insert(str); father[i] = father_id[Num_dots - 1]; //记录该节点的父亲节点 } } } void Cal () { set<string>::iterator it; for (int i=0;i<n;i++) for (it=st[i].begin();it!=st[i].end();it++) { int tmp = mp[*it]; Num_bro[tmp] = st[i].size(); //统计兄弟数量 } } void DFS (int u,int dep) { F[++curID]=u; B[curID]=dep; ID[u]=curID; //在循环外,只有第一次被访问时被赋值 set<string>::iterator it; for (it = st[u].begin();it != st[u].end();it++) { int v = mp[*it]; DFS(v,dep+1); F[++curID]=u; B[curID]=dep; } } void init_RMQ () //rmq的初始化 { int i,j,x,y; for (i=1;i<=curID;i++) RMQ[i][0]=i; for (j=1;(1<<j)<=curID;j++) for (i=1;i+(1<<j)-1<=curID;i++) { x=RMQ[i][j-1]; y=RMQ[i+(1<<(j-1))][j-1]; RMQ[i][j]=B[x]<B[y]?x:y; } } void Dfs_out (int u) //顺序输出,这里set直接排序了 { int v; set<string>::iterator it; for (it=st[u].begin();it != st[u].end();it++) { v = mp[*it]; printf("%s\n",data[v]); Dfs_out(v); } } int getLCA (int a,int b) { int k; a=ID[a]; b=ID[b]; if (a>b) k=a,a=b,b=k; k=(int)(log(1.0+b-a)/log(2.0)); if (B[RMQ[a][k]] < B[RMQ[b-(1<<k)+1][k]]) return F[RMQ[a][k]]; else return F[RMQ[b-(1<<k)+1][k]]; } void Deal () //LCA在线算法 lca+rmq的过程 { int q; string s1,s2; scanf("%d",&q); while (q--) { cin>>s1; if (s1[0] == 'L') { printf("%s\n",data[0]); Dfs_out (0); } else if (s1[0] == 'b') { cin>>s2; printf("%d\n",Num_bro[mp[s2]]); } else { cin>>s1>>s2; int u = mp[s1]; int v = mp[s2]; int k=getLCA(u,v); if (k==u || k==v) k=father[k]; for (int i=0; i<strlen(data[k]);i++) if (data[k][i] != '.') printf("%c",data[k][i]); printf("\n"); } } } int main () { while (scanf("%d",&n) && n) { init (); Input (); Cal (); DFS (0,0); init_RMQ(); Deal (); } return 0; }
相关文章推荐
- hdu 4409 Family Name List LCA +stl
- HDU 4409 Family Name List ( 模拟 + LCA)
- HDU 4409 Family Name List(LCA)
- HDU-4409 Family Name List LCA求解,TC+DFS || tarjan
- HDU 4409 - Family Name List(模拟树+lca)
- HDU 4409 Family Name List --乱搞、LCA
- HDU 4409 Family Name List --乱搞、LCA
- Family Name List (HDU 4409)
- hdu 4409 Family Name List
- HDU 4409 Family Name List 简单树操作
- hdu 4409 Family Name List
- hdu 4409 Family Name List 金华赛区1010 (解题报告)
- hdu 1412 (STL list)
- HDU 4409 大模拟 + LCA
- hdu 4409 LCA
- 【模拟】 hdu4409 Family Name List
- ACM网络赛金华赛区的一道关于树的题:Family Name List
- HDU 5217 list 的学习与使用 和与其他STL的区别
- hdu 1276 士兵队列训练问题(STL的list)
- STL----list