程序设计基础实验课 单元六的题-UVA10410 TreeReconstruction 树重建
入门指南题面:
洛谷题面:
观看的题解:https://www.cnblogs.com/jerryRey/p/4622927.html
对样例区样例画的一些图:
题目的一些争议:
bfs[u] + 1 == bfs[b] && v < u的情况被默认看作后兄弟节点
//-------------------------代码---------------------------- //#define int ll const int N = 2e5+10; int n,k; int a[N],b[N],bfs[N],fa[N]; vector<int> g[N]; void solve() { // while(cin>>n,n) { cin>>n; int t,v; for(int i = 1;i <= n;i ++ ) { cin>>t,bfs[t] = i,g[i].clear();// bfs序 } int root; cin>>root; stack<int> stk; stk.push(root);// for(int i = 2;i <= n;i ++ ) { cin>>v; while(1) { int u = stk.top(); if(u == root // 如果是根节点 || bfs[u] + 1 < bfs[v] //bfs序 + 1 比当前节点小 ,说明是子节点 ,不是后兄弟节点 || (bfs[u] + 1 == bfs[v] && u > v) // bfs序 + 1 等于当前节点, 并且 u > t 这种情况,t 一定不是 u 的后兄弟节点 //且 前面的节点比当前节点大 说明 u 没有后兄弟结点 u是bfs中u所在层的最后一个结点, // 这时候u没有后兄弟结点,所以后面的结点一定都是他的后代结点,那么v就一定可以等效作u的兄弟结点而不改变bfs,dfs序。 ) { g[u].pb(v); // 将最新的节点放入栈中 stk.push(v); break; } else { // 当一条分支a遍历完,进入下一条分支b的时候,a 上面的节点必然都不是 分支b 上的节点的父节点,所以将它们依次弹出 stk.pop(); } } } for(int i = 1;i <= n;i ++ ) { cout<<i<<':'; for(int j = 0,sz = g[i].size();j < sz;j ++ ) { cout<<' '<<g[i][j]; } cout<<endl; } // ps: 这题有一个小问题就是 bfs[u] + 1 == bfs[v] 且 u < v 的时候, 是没法判断 v 是 u 的后兄弟节点还是子节点的,但根据网上的题解,大家都默认把它看成了后兄弟节点 // 且本身就是结点小的优先被遍历,所以不需要在意升序排列 // } } void main_init() {} signed main(){ clapping();TLE; main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 构造 二分 贪心 递推 模拟 9 9 4 3 5 1 2 8 7 6 9 4 3 1 7 2 6 5 8 9 9 3 4 5 1 2 8 7 6 9 3 4 1 7 2 6 5 8 6 9 3 4 5 1 2 9 3 4 5 1 2 */ //------------------------------------------------------------