リンク:
タイトルの意味:
n 個のノードを持つバイナリ ツリー。隣接するノード間で1 つの重みを移動できるたびに、ノードの重みの合計はn になります。
各ノードが 1 になる最小回数を求めます。
ほどく:
ツリー構造が与えられた場合、最初に DFS/BFS を実行します。n は大きくなく、何気なく無謀です
まず、各ノードに 1 だけ残す必要があり、葉ノードが 1 でない場合は、親ノードを経由して移動する必要があることがわかります。
したがって、リーフ ノードが 1 にプリセットされ、必要なコストが親ノードに転送されている限り、リーフ ノードはツリーから削除できます (処理されているため)。
次の状況を分析します。
1. 葉ノードの値が 1: 葉ノードであり、番号も適切であるため、移動の可能性は 0 です。これは、葉ノードが処理され、ツリーから削除できることを意味します。
2. リーフ ノードの値は 1 未満です。リーフ ノードには固有のソース (親ノード) があるため、コスト転送を実行し、最初に 1-val 回の移動を費やし、同時に親の値を減らすことができます。ノードを1-valで削除し、それ自体を消去します。移動に関与しなくなるためです(親ノードが0である可能性があるため、削減後に負の数が発生します。これは理解しやすく、重みが使用されます)金貨の代わりに)
3. リーフ ノードの値は 1 より大きいです。リーフ ノードには一意の宛先 (親ノード) があるため、コスト転送を実行できます。最初に val-1 回の移動を費やし、すべての冗長な重みを親ノードに与えます。モバイルに関与しなくなったため、それ自体を消去します
4. すべてのリーフ ノードがツリーから消去されると、その元の親ノードが新しいリーフ ノードと呼ばれ、前の 3 つのケースが処理されます。
5. 最後にルートノードだけが残った場合、重みの合計はnなので、各ノードが1になった時点で消去され、ルートノードの処理時に値が1になる必要があります。
実際のコード:
#include<bits/stdc++.h>
using namespace std;
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
void add(vector<int> &temp,TreeNode *root,int mao)//建树
{
root->val=temp[mao-1];
if( mao*2-1<temp.size() && temp[mao*2-1]!=-1)//left child add
{
root->left=new TreeNode;
add(temp,root->left,mao*2);
}
if( mao*2<temp.size() && temp[mao*2]!=-1)//right child add
{
root->right=new TreeNode;
add(temp,root->right,mao*2+1);
}
}
void solve(TreeNode* now,int &ans,TreeNode* father)
{
if(now->left!=nullptr) solve(now->left,ans,now);//DFS
if(now->right!=nullptr) solve(now->right,ans,now);//DFS
//if(father==nullptr) return;
//最后只剩根节点的时候,由于权值总和为n,当每个节点为1的时候才抹去,则处理到根节点时值一定为1
//cout<<now->val<<" "<<ans<<endl;
if(now->val<1 && father!=nullptr)
{
ans+= 1-now->val;//计算移动次数
father->val-= 1-now->val;//代价转移
now->val=1;//设为1
}
if(now->val>1 && father!=nullptr)
{
ans+= now->val-1;//计算移动次数
father->val+= now->val-1;//代价转移
now->val=1;//设为1
}
}
int distributeCoins(TreeNode* root)
{
int ans=0;
solve(root,ans,nullptr);
return ans;
}
int main()
{
int n;cin>>n;
vector<int> temp;TreeNode root;
for(int i=1;i<=n;i++)
{
int t;cin>>t;temp.push_back(t);
}
add(temp,&root,1);//建树
int ans=distributeCoins(&root);
cout<<ans<<endl;
return 0;
}
制限:
- ツリー内のノードの数は、
n
1 <= n <= 100
0 <= Node.val <= n
- のすべての
Node.val
値の合計は、n