2023-07-14 リコウの毎日の質問

リンク:

979. 二分木にコインを割り当てる

タイトルの意味:

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

おすすめ

転載: blog.csdn.net/Fei_WuYan/article/details/131731392