LINK
也可以这样,根据 A + B A+B A+B节点数计算出前 k k k层节点是满的
那么若 B < 2 k − 1 B<2^k-1 B<2k−1,根据二进制的性质,可以从中抽取若干层都放 2 2 2节点
那么剩下的都是 1 1 1节点,就随便构造了
若 B > = 2 k − 1 B>=2^k-1 B>=2k−1,贪心的想,让前 k k k层全部放 2 2 2节点
然后把剩余的 A , B A,B A,B节点从根节点递归下去,每次都二分
到了第 k + 1 k+1 k+1层就可以开始构造了
(当然还是有小概率凑不成,再 d f s dfs dfs验证一遍即可)
#include <iostream> using namespace std; const int maxn = 1e6+10; int A,B,ok[55],flag,k,id; int val[maxn],ls[maxn],rs[maxn]; int flag1,flag2,mx1,mx2; void dfs(int u,int fa,int deep,int suma,int sumb) { if( ok[deep] || flag ) val[u] = 2; else val[u] = 1; if( deep+1==k ) { if( sumb ) rs[u] = ++id, val[id] = 2; if( suma ) ls[u] = ++id, val[id] = 1; if( suma==2 && sumb ) ls[id] = id+1, ++id, val[id] = 1; if( suma==2 && !sumb ) rs[u] = ++id, val[id] = 1; return; } ls[u] = u<<1; rs[u] = u<<1|1; dfs( ls[u], u , deep+1, suma/2, sumb/2 ); dfs( rs[u], u , deep+1, suma-suma/2, sumb-sumb/2 ); } int sum[maxn]; void DP(int u) { if( !u ) return; DP( ls[u] ); DP( rs[u] ); if( abs( sum[ls[u]]-sum[rs[u]] )>1 ) { cout << -1; exit(0); } sum[u] = sum[ls[u]]+sum[rs[u]]+val[u]; } int main() { cin >> A >> B; for(int i=0;i<=20;i++) { if( (B>>i)&1 ) ok[i] = 1; if( (1<<i)-1<=A+B ) k = i; } if( (1<<k)-1<B ) B -= (1<<k)-1,flag = 1; else A -= (1<<k)-1-B, B = 0; if( A<B ){ cout << -1; return 0; } id = (1<<k)-1; dfs(1,1,0,A,B); DP(1); for(int i=1;i<=id;i++) cout << val[i] << " " << ls[i] << " " << rs[i] << endl; }
如果权值只有 1 1 1,那么很容易可以构造答案
如果权值只有 2 2 2,那么几乎不可能构造出答案(除非完全铺满二叉树的每一层)
进一步发现,如果 ( a , b ) (a,b) (a,b)可以构造出解,那么 ( a + 2 , b − 1 ) (a+2,b-1) (a+2,b−1)也可以构造出解
因为可以使用两个权值 1 1 1代替掉那个权值为 2 2 2的节点
如果无法构造解,一定是因为奇数个 2 2 2无法平均分配给两个儿子,又没有足够的 1 1 1来平衡他们
所以当权值为 2 2 2的节点为奇数个时,我们在根节点放权值 2 2 2的节点
然后平均分配给子树
权值为 1 1 1的节点再去填充剩余的空节点,有多余再同样二分
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6+19; int val[maxn],vis[maxn]; void dfs1(int u,int B) { if( !B ) return; vis[u] = 1; if( B&1 ) val[u] = 2,B--; dfs1( u<<1,B/2 ),dfs1( u<<1|1,B/2 ); } void dfs2(int u,int& A) { if( !val[u] ) val[u] = 1, A--; if( vis[u<<1] ) dfs2( u<<1,A ); if( vis[u<<1|1] ) dfs2( u<<1|1,A ); } void dfs3(int u,int A) { if( !val[u] && A ) val[u] = 1, A--; if( A ) dfs3( u<<1,A/2 ),dfs3( u<<1|1,A-A/2 ); } int id,ID[maxn],top[maxn]; void dfs4(int u) { if( !val[u] ) return; top[++id] = u; ID[u] = id; dfs4( u<<1 ); dfs4( u<<1|1 ); } int main() { int A,B; scanf("%d%d",&A,&B ); dfs1( 1,B ); dfs2( 1,A ); if( A<0 ) cout << -1; else { dfs3(1,A); dfs4(1); for(int i=1;i<=id;i++) { int u = top[i]; printf("%d %d %d\n",val[u],ID[u<<1],ID[u<<1|1] ); } } }