HDU4409-LCA模拟

给一个家谱,回答给的操作结果。

  1)L 按照字典序排序儿子,输出整个家谱。

  2)b 求出所给name的所有兄弟。

  3)c 求出两个name的LCA

读入数据时,我用一个curfather数组维护固定深度的爸爸,之后就可以方便的将所给的数据形式转换成邻接表建图,同时使用map存储name和id号。Tree结构体数组存储每个人的信息,父亲,儿子(vector存储,方便排序等操作),name,深度。

L操作将每个人的儿子排序,递归打印。

b操作直接找到他父亲,用size函数计算儿子数。

c操作用st表+DFS在线求解。

这道题还有两个坑,根的兄弟要输出1,a和b的lca是a或b时,所求为其lca的父亲。

还有就是递归打印会暴栈,要交C++用黑科技的扩栈语句。

//这个题用了我好久,先学LCA,再纠结怎么处理输入数据,立下不a出来不吃饭的flag,最终a了。。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <ctype.h>
  5 #include <cstdlib>
  6 #include <cstdio>
  7 #include <vector>
  8 #include <string>
  9 #include <queue>
 10 #include <stack>
 11 #include <cmath>
 12 #include <set>
 13 #include <map>
 14 #pragma comment(linker,"/STACK:102400000,102400000")
 15 
 16 using namespace std;
 17 
 18 const int maxn = 300100;
 19 int N,M,T,rmq[2*maxn];
 20 
 21 struct ST
 22 {
 23     int stTable[2*maxn][20];
 24     int prelog2[2*maxn];
 25 
 26     void init(int n)
 27     {
 28         prelog2[1] = 0;stTable[1][0] = 1;
 29         for(int i=2;i <= n;i++)
 30         {
 31             prelog2[i] = prelog2[i-1];
 32             stTable[i][0] = i;
 33             if((1 << (prelog2[i]+1)) == i) ++prelog2[i];
 34         }
 35         for(int i=n;i > 0;i--)
 36         {
 37             for(int j=1;(i+(1<<j)-1) < n;j++)
 38             {
 39                 stTable[i][j] = rmq[stTable[i][j-1]] < rmq[stTable[i+(1<<(j-1))][j-1]] ? stTable[i][j-1] : stTable[i+(1<<(j-1))][j-1];
 40             }
 41         }
 42     }
 43 
 44     int query(int a,int b)
 45     {
 46         if(a > b) swap(a,b);
 47         int k = prelog2[b-a+1];
 48         return rmq[stTable[a][k]] < rmq[stTable[b-(1<<k)+1][k]] ? stTable[a][k] : stTable[b-(1<<k)+1][k];
 49     }
 50 };
 51 
 52 struct Node
 53 {
 54     int to,next;
 55 };
 56 
 57 struct LCA
 58 {
 59     int n;
 60     Node edge[2*maxn];
 61     int tol,head[maxn],Dfs[2*maxn],P[maxn],cnt;
 62     bool vis[maxn];
 63     ST st;
 64 
 65     void init(int n)
 66     {
 67         this->n = n;
 68         tol = 0;
 69         memset(head,-1,sizeof head);
 70     }
 71 
 72     void add_edge(int a,int b)
 73     {
 74         edge[tol].to = b;
 75         edge[tol].next = head[a];
 76         head[a] = tol++;
 77         edge[tol].to = a;
 78         edge[tol].next = head[b];
 79         head[b] = tol++;
 80     }
 81 
 82     int query(int a,int b)
 83     {
 84         //printf("%d %d:%d
",P[a],P[b],st.query(P[a],P[b]));
 85         return Dfs[st.query(P[a],P[b])];
 86     }
 87 
 88     void dfs(int a,int deepth)
 89     {
 90         vis[a] = true;
 91         ++cnt;
 92         Dfs[cnt] = a;
 93         rmq[cnt] = deepth;
 94         P[a] = cnt;
 95         //printf("cnt=%d
",cnt);
 96         for(int i = head[a];i != -1;i = edge[i].next)
 97         {
 98             int v = edge[i].to;
 99             if(vis[v]) continue;
100             dfs(v,deepth+1);
101             ++cnt;
102             Dfs[cnt] = a;
103             rmq[cnt] = deepth;
104         }
105     }
106 
107     void solve(int root)
108     {
109         memset(vis,false,sizeof vis);
110         cnt = 0;
111         //printf("root=%d
",root);
112         dfs(root,0);
113         st.init(2*n-1);
114     }
115 
116 }lca;
117 
118 int num = 0;
119 int curfather[maxn];
120 struct Node_son
121 {
122     int deepth;
123     int fa;
124     vector<int> son;
125     string name;
126 }Tree[maxn];
127 
128 bool cmpson(const int a,const int b) { return Tree[a].name < Tree[b].name;}
129 
130 void Print_Tree(int root)
131 {
132     for(int i=0;i<Tree[root].deepth;i++) cout << '.';
133     cout << Tree[root].name << endl;
134     if(Tree[root].son.empty()) return;
135     sort(Tree[root].son.begin(),Tree[root].son.end(),cmpson);
136 
137     for(int i=0;i < (int)Tree[root].son.size();i++)
138     {
139         Print_Tree(Tree[root].son[i]);
140     }
141 }
142 
143 int main()
144 {
145     while(cin>>N && N)
146     {
147         lca.init(N);
148         map <string ,int > m;
149         memset(curfather,0,sizeof curfather);
150 
151         for(int i=0;i<N;i++)
152         {
153             cin>>Tree[i].name;
154             Tree[i].son.clear();
155             int lev = 0;
156             for(int t = 0;t < (int)Tree[i].name.size();t++)    
157             {
158                 if(Tree[i].name[t] != '.') break;
159                 else lev++;
160             }
161             Tree[i].name.erase(Tree[i].name.begin(),Tree[i].name.begin()+lev);
162             m.insert(pair<string,int>(Tree[i].name,i));
163             Tree[i].deepth = lev;
164 
165             curfather[lev+1] = i;
166             if(lev == 0) continue; 
167             Tree[i].fa = curfather[lev];
168             Tree[Tree[i].fa].son.push_back(i);
169             lca.add_edge(Tree[i].fa+1,i+1);
170         }
171         string op;cin >> T;
172         lca.solve(1);
173 
174         while(T--)
175         {
176             cin >> op;
177             if(op[0] == 'L')       //重构树,字典序
178             {
179                 Print_Tree(0);
180             }
181             else if(op[0] == 'b')  //兄弟数
182             {
183                 string son;
184                 cin >> son;
185                 if(son == Tree[0].name) cout << 1 <<endl;
186                 else cout << Tree[ Tree[m[son]].fa ].son.size()<<endl;
187             }
188             else if(op[0] == 'c')  //LCA DFS+ST
189             {
190                 string son1,son2;
191                 cin >> son1 >> son2;
192                 int lllca = lca.query(m[son1]+1,m[son2]+1) - 1;
193                 if(lllca == m[son1] || lllca == m[son2]) 
194                     cout << Tree[Tree[lllca].fa].name << endl;
195                 else cout << Tree[ lca.query(m[son1]+1,m[son2]+1) - 1].name<<endl;
196             }
197         }
198     }    
199 }
原文地址:https://www.cnblogs.com/helica/p/4792885.html