树相关题目

树叶子节点

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110;
int head[N],e[N],ne[N],idx;
int n,m;

void add(int a,int b)
{
    e[idx] = b;
    ne[idx] = head[a];
    head[a] = idx;
    idx++;
} 

int max_depth;
int node_num[N];//每一层节点的数量
void dfs(int node,int depth)
{
    if(head[node]==-1){//如果是叶子结点
        node_num[depth]++;
        max_depth = max(depth,max_depth);
        return;
    }
    
    for(int i=head[node];i!=-1;i=ne[i]){
        dfs(e[i],depth+1);
    }
}

int main()
{
    cin >> n >> m;
    memset(head,-1,sizeof head);
    while(m--)
    {
        int id,k;
        cin >> id >>k;
        while(k--){
            int num;
            cin >> num;
            add(id,num);
        }
    }
    dfs(1,0);
    for(int i=0;i<=max_depth;i++) cout << node_num[i]<<" ";
    return 0;
}

树的遍历

map的一些操作

map操作参考

//头文件
#include<map>
#include <iostream>
#include <string>
using namespace std;

//map<int, string> ID_Name; //建立一个空的map

// 使用{}赋值是从c++11开始的,因此编译器版本过低时会报错,如visual studio 2012
map<int, string> ID_Name = {
                { 2015, "Jim" },
                { 2016, "Tom" },
                { 2017, "Bob" } };

int main()
{
    cout << ID_Name[2015] << endl;  //输出 Jim
    ID_Name[2020] = "ning";//也可以直接这么添加一个没有的元素
    cout << ID_Name[2020] << endl;  //输出ning
    
    //遍历建立的map
    for(map<int,string>::iterator it = ID_Name.begin();it!=ID_Name.end();it++){
        cout << it->first << ":" << it->second << endl;
    }
    //find()方法返回值是一个迭代器,成功返回迭代器指向要查找的元素,
    //失败返回的迭代器指向end。count()方法返回值是一个整数,1表示有这个元素,0表示没有这个元素
    cout << ID_Name.count(2021);//因为没有2021这个元素,所以返回0
    return 0;
}

题目

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
const int N = 40;
int inorder[N],postorder[N];//中序遍历与后序遍历
map<int,int> left_child,right_child,position;
//这个是二叉树所以直接用left_child[node]存node的左孩子
//用right_child[node]存node的右孩子
//position[node]是node这个节点在中序遍历中的位置

int build(int in_l,int in_r,int post_l,int post_r)
{
    int root = postorder[post_r]; //后序遍历的最后一个值就是子树根节点的值
    int pos = position[root];
    if(in_l < position[root]) left_child[root]  = build(in_l,pos-1,post_l,post_l+pos-1-in_l); //如果左子树存在
    if(in_r > position[root]) right_child[root] = build(pos+1,in_r,post_r-1-(in_r-pos-1),post_r-1); //如果右子树存在
    return root;
}

int main()
{
    int n;
    cin >> n;
    for(int i=0;i<n;i++) cin >> postorder[i];
    for(int i=0;i<n;i++){
        cin >> inorder[i];
        position[inorder[i]] = i;
    }
    int root = build(0,n-1,0,n-1);
    queue<int> q;
    q.push(root);
    while(!q.empty()){
        int node = q.front();
        if(left_child.count(node)) q.push(left_child[node]);
        if(right_child.count(node)) q.push(right_child[node]);
        cout << node << " ";
        q.pop();
    }
    return 0;
}
dfs另一种写法
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
const int N = 40;
int postorder[N],inorder[N];
int n;
map<int,int> left_child,right_child,pos;

int dfs(int inl,int inr,int postl,int postr)
{
    if(inl > inr) return 0; //用0表示没有子树了
    int root = postorder[postr];
    int p = pos[root];//根节点在中序遍历中的位置
    left_child[root] = dfs(inl,p-1,postl,postl+p-1-inl);
    right_child[root] = dfs(p+1,inr,postr-1-(inr-p-1),postr-1);
    return root;
}

int main()
{
    cin >> n;
    for(int i=0;i<n;i++) cin >> postorder[i];
    for(int i=0;i<n;i++){
        cin >> inorder[i];
        pos[inorder[i]] = i;
    }
    int root = dfs(0,n-1,0,n-1);
    queue<int> q;
    q.push(root);
    while(!q.empty())
    {
        int node = q.front();
        q.pop();
        if(left_child[node]) q.push(left_child[node]);
        if(right_child[node]) q.push(right_child[node]);
        cout << node << " ";
    }
    return 0;
}

再次树遍历

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <map>
#include <stack>
using namespace std;

const int N = 40;
int n;
int preorder[N];  //push连起来就是前序遍历
int inorder[N];   //pop连起来就是中序遍历
map<int,int> left_child,right_child,pos;  //pos是节点在中序遍历中的位置

int build(int pre_l,int pre_r,int in_l,int in_r)
{
    int root = preorder[pre_l];
    int pos_in = pos[root];
    if(pos_in > in_l) left_child[root] = build(pre_l + 1, pre_l + pos_in - in_l ,in_l,pos_in-1);
    if(pos_in < in_r) right_child[root] = build(pos_in + pre_l + 1- in_l,pre_r,pos_in+1,in_r);
    return root;
}

void postorder(int node)
{
    int now_node = node;
    if(left_child.count(now_node)!=0) postorder(left_child[now_node]);
    if(right_child.count(now_node)!=0) postorder(right_child[now_node]);
    cout << now_node << " ";
}

int main()
{
    cin >> n;
    int m = 2*n;
    stack<int> st;
    int i = 0,j = 0;
    while(m--){
        string s;
        cin >> s;
        if(s=="Push"){
            int num;
            cin >> num;
            st.push(num);
            preorder[i++] = num; 
        }
        else if(s=="Pop"){
            int num = st.top();
            st.pop();
            inorder[j] = num;
            pos[num] = j;
            j++;
        }
    }
    int root = build(0,n-1,0,n-1);
    postorder(root);
    
    return 0;
}

最深的根

在这里插入图片描述

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1e4+10;
const int M = 2*N;
int n;//节点数量

int e[M],ne[M],h[M],idx;
void add(int a,int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}

int p[M];
int find(int x)
{
    if(p[x]!=x) p[x] = find(p[x]);
    return p[x];
}

int dfs(int u,int father)//dfs返回当前节点u到达最深的长度
{
    int depth = 0;
    for(int i=h[u];i!=-1;i=ne[i])
    {
        if(e[i]==father) continue;//因为是无向图,避免重复遍历
        
        depth = max(depth,dfs(e[i],u)+1);
    }
    return depth;
}

int main()
{
    cin >> n;
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++) p[i] = i;
    int k = n; //连通块的数量
    for(int i=0;i<n-1;i++){
        int a,b;
        cin >> a >> b;
        add(a,b),add(b,a);
        if(find(a)!=find(b)){
            p[find(a)] = find(b);
            k--;
        }
    }
    if(k>1) printf("Error: %d components",k);
    else{
        vector<int> res;//存储可以最深的根节点
        int max_depth = -1;
        for(int i=1;i<=n;i++){
            int now_depth = dfs(i,-1);//dfs(当前节点,父节点)
            if(now_depth > max_depth){
                max_depth = now_depth;
                res.clear();
                res.push_back(i);
            }
            else if(now_depth == max_depth) res.push_back(i);
        }
        for(auto i:res) cout << i <<endl;
        
        
    }
    return 0;
}

判断二叉搜索树

在这里插入图片描述

//这个题的意思是:
//给定一个前序序列,这个前序序列可能是 1. 左小右大的BST的前序序列
//                                     2. 左大右小的BST的前序序列(即:镜像)
//要么输出左小右大类BST的后序序列
//要么输出左大右小的BST的后序序列
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1010;
int n;
int preorder[N],inorder[N];
int postorder[N],cnt = 0;

bool build(int inl,int inr, int prel, int prer, int type)
{
    if(inl > inr) return true;
    int root = preorder[prel];
    int k;
    if(type==0){
        for(k=inl;k<=inr;k++){
            if(inorder[k]==root) break;
        }
        if(k>inr) return false;
    }
    else{
        for(k=inr;k>=inl;k--){
            if(inorder[k]==root) break;
        }
        if(k<inl) return false;
    }
    bool res = true;
    if(!build(inl,k-1,prel+1,prel+1+(k-1-inl),type)) res = false;
    if(!build(k+1,inr,prel + 1 + (k - 1 - inl) + 1,prer,type)) res = false;
    postorder[cnt] = root;
    cnt ++;
    return res;
}




int main()
{
    cin >> n;
    for(int i=0;i<n;i++){
        cin >> preorder[i];
        inorder[i] = preorder[i];
    }
    sort(inorder,inorder+n);
    if(build(0,n-1,0,n-1,0)){//代表第一种无翻转即左小右大
        cout << "YES" << endl;
        for(int i=0;i<n;i++) cout << postorder[i] << " ";
    }
    else{
        cnt = 0;
        reverse(inorder,inorder+n);//镜像的树中序遍历是倒序的
        if(build(0,n-1,0,n-1,1)){
            cout << "YES" << endl;
            for(int i=0;i<n;i++) cout << postorder[i] <<" ";
        }
        else cout << "NO";
    }
    return 0;
}

完全二叉搜索树

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1010;
int w[N],tree[N];
int n;
int k = 0;

void dfs(int u,int &k){//u表示tree中的几号点,k表示现在应该填w中的k号即w[k]
    if(u*2 <= n) dfs(u*2,k);
    tree[u] = w[k];
    k++;
    if((u*2+1)<=n) dfs(u*2+1,k);
}

int main()
{
    cin >> n;
    for(int i=0;i<n;i++) cin >> w[i];
    sort(w,w+n);
    dfs(1,k);
    for(int i=1;i<=n;i++) cout << tree[i] << " ";
    return 0;
}

构建二叉搜索树

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 110;
int n;
int left_child[N],right_child[N];//i号节点的左右儿子各是几号节点
int tree[N],k = 0; //代表i号节点的值是多少
                   //k代表当前应该填写第几个w中的数
int w[N];    //代表每个节点的权值
void dfs(int u,int& k)
{
    if(u==-1) return;
    dfs(left_child[u],k);
    tree[u] = w[k++];
    dfs(right_child[u],k);
}

int main()
{
    cin >> n;
    for(int i=0;i<n;i++){
        int l,r;
        cin >> l >> r;
        left_child[i] = l;
        right_child[i] = r;
    }
    for(int i=0;i<n;i++) cin >> w[i];
    sort(w,w+n);
    dfs(0,k);
    queue<int> q;
    q.push(0);
    while(!q.empty()){
        int node = q.front();
        q.pop();
        if(left_child[node]!=-1) q.push(left_child[node]);
        if(right_child[node]!=-1) q.push(right_child[node]);
        cout << tree[node] << " ";
    }
    return 0;
}

反转二叉树

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 20;
int n;
int left_child[N],right_child[N];
bool has_father[N]; //用于找到根节点

void dfs(int u)
{
    if(u==-1) return;
    dfs(right_child[u]);
    cout << u << " ";
    dfs(left_child[u]);
}

int main()
{
    cin >> n;
    memset(left_child,-1,sizeof left_child);
    memset(right_child,-1,sizeof right_child);
    
    for(int i=0;i<n;i++){
        char l,r;
        cin >> l >> r;
        if(l!='-'){
            left_child[i] = l - '0';
            has_father[left_child[i]] = true;
        }
        if(r!='-'){
            right_child[i] = r - '0';
            has_father[right_child[i]] = true;
        }
    }
    int root = 0;
    while(has_father[root]) root++;
    
    queue<int> q;
    q.push(root);
    while(!q.empty())
    {
        int node = q.front();
        q.pop();
        if(right_child[node]!=-1) q.push(right_child[node]);
        if(left_child[node]!=-1) q.push(left_child[node]);
        cout << node << " ";
    }
    cout << endl;
    dfs(root);
    return 0;
}

完全二叉树

在这里插入图片描述

//读入这个树的时候把这个树看做完全二叉树,然后求出最后一个节点的编号就好了
//如果是完全二叉树,最后一个节点正好就是n
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 30;
int n;
int l[N],r[N];
bool has_father[N];

int lastid,maxk = 0;
void dfs(int u,int k)//u是节点的值, k是节点在完全二叉树中的位置 
{
    if(u==-1) return;
    if(k > maxk){
        lastid = u;
        maxk = k;
    }
    if(l[u]!=-1) dfs(l[u],2*k);
    if(r[u]!=-1) dfs(r[u],2*k+1);
}

int main()
{
    cin >> n;
    memset(l,-1,sizeof l);
    memset(r,-1,sizeof r);
    for(int i=0;i<n;i++){
        string a,b;
        cin >> a >> b;
        if(a!="-"){
            l[i] = stoi(a);
            has_father[l[i]] = true;
        }
        if(b!="-"){
            r[i] = stoi(b);
            has_father[r[i]] = true;
        }
    }
    int root = 0;
    while(has_father[root]) root++;
    
    dfs(root,1);
    if(maxk==n){
        cout << "YES " << lastid << endl;
    }
    else cout << "NO " << root << endl;
    return 0;
    
}

二叉搜索树最后两层节点数量

在这里插入图片描述

#include <algorithm>
#include <iostream>
using namespace std;
const int N = 1010;
int left_child[N],right_child[N];
//一共有n个节点,给每个节点都编上号i,left_child,right_child中存的都是节点编号i
int a[N];  //a[i]中存的是节点权值
int n;

int idx = 0; //idx表示现在已经 插完 几个节点了
void insert(int& u, int value)//在u号节点后插入value值
{
    if(u==0){
        idx++;
        u = idx;
    }
    else if(a[u]>=value) insert(left_child[u],value);//insert这里是用的引用,所以如果left_child[u]是0的话,下一次调用insert会更新的
    else insert(right_child[u],value);
}

int level[N],max_depth = -1;
void dfs(int u,int depth)
{
    if(u==0) return;
    level[depth]++;
    max_depth = max(max_depth,depth);
    dfs(left_child[u],depth+1);
    dfs(right_child[u],depth+1);
}

int main()
{
    cin >> n;
    for(int i=1;i<=n;i++){
        int w;
        cin >> w;
        a[i] = w;
    }
    
    int root = 0;
    for(int i=1;i<=n;i++) insert(root,a[i]);
    
    dfs(root,1);
    int n1 = level[max_depth];
    int n2 = level[max_depth-1];
    printf("%d + %d = %d",n1,n2,n1+n2);
    
    return 0;
}

前序和后序遍历

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 40;
int n;
int pre[N],post[N];

int build(int prel,int prer,int postl,int postr,string& res)
{
    if(prel > prer) return 1;
    if(pre[prel] != post[postr]) return 0;
    
    int cnt = 0;
    for(int i=prel;i<=prer;i++){
        string res_left,res_right;
        int cnt1 = build(prel+1,i,postl,postl+i-prel-1,res_left);
        int cnt2 = build(i+1,prer,postl+i-prel,postr-1,res_right);

        if(cnt1 && cnt2){
            cnt += cnt1*cnt2;
            res = res_left + to_string(pre[prel])+" " + res_right;
            if(cnt > 1) break;
        }
    }
    return cnt;
}

int main()
{
    cin >> n;
    for(int i=0;i<n;i++) cin >> pre[i];
    for(int i=0;i<n;i++) cin >> post[i];
    string res;
    int cnt = build(0,n-1,0,n-1,res);
    if(cnt > 1) puts("No");
    else puts("Yes");
    //不能用for循环一次输出一位数,因为有些数是两位的,这样就给拆开了
    res.pop_back();
    cout << res;
    return 0;
}

Z字形遍历二叉树

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
const int N = 40;
int n;
int inorder[N],postorder[N];
map<int,int> left_child,right_child,pos;

int build(int inl,int inr, int postl, int postr)
{
    int root = postorder[postr];
    int k = pos[root];
    if(inl < k) left_child[root] = build(inl,k-1,postl,postl+k-1-inl);
    if(inr > k) right_child[root] = build(k+1,inr,postr-inr+k,postr-1);
    return root;
}



int main()
{
    cin >> n;
    for(int i=0;i<n;i++){
        cin >> inorder[i];
        pos[inorder[i]] = i;
    }
    for(int i=0;i<n;i++) cin >> postorder[i];
    int root = build(0,n-1,0,n-1);
    
    
    int q[N];
    q[0] = root;
    int hh = 0, tt = 0;
    int level = 0;  //当前的层数
    while(hh <= tt)
    {
        int head = hh;
        int tail = tt;  //head,tail记录每一层节点在队列中的范围
        while(hh <= tail)
        {
            int now_node = q[hh++];
            if(left_child.count(now_node)) q[++tt] = left_child[now_node];
            if(right_child.count(now_node)) q[++tt] = right_child[now_node];
        }
        level++;
        if(level % 2 == 1) reverse(q+head,q+tail+1);
        
    }
    cout << q[0];
    for(int i=1;i<=tt;i++) cout<< " " << q[i];
    return 0;
}

后序遍历

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const int N = 50010;
int n;
int preorder[N],inorder[N];
int postorder[N],idx = 0;
map<int,int> left_child,right_child,pos;

int build(int prel, int prer, int inl, int inr)
{
    int root = preorder[prel];
    int k = pos[root];
    if(inl < k) left_child[root] = build(prel+1,prel+1+k-1-inl,inl,k-1);
    if(inr > k) right_child[root] = build(prer-(inr-k-1),prer,k+1,inr);
    return root;
}

void dfs(int u)
{
    if(u==0) return;
    dfs(left_child[u]);
    dfs(right_child[u]);
    postorder[idx++] = u;
}


int main()
{
    cin >> n;
    for(int i=0;i<n;i++) cin >> preorder[i];
    for(int i=0;i<n;i++){
        cin >> inorder[i];
        pos[inorder[i]] = i;
    }
    int root = build(0,n-1,0,n-1);
    dfs(root);
    cout << postorder[0] << endl;
    
    return 0;
}

PAT1053等重路径

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 110;
bool g[N][N];
int n,m,s;
int w[N];
bool leaf[N]; //是否为叶子节点
vector<vector<int>> res;

void dfs(int u,int weight,vector<int>& path)
{
    if(leaf[u]){
        if(weight==s) res.push_back(path);
        return;
    }
    for(int i=0;i<n;i++){
        if(g[u][i]){
            path.push_back(w[i]);
            dfs(i,weight+w[i],path);
            path.pop_back();
        }
    }
}

int main()
{
    cin >> n >> m >> s;
    for(int i=0;i<n;i++) cin >> w[i];
    for(int i=0;i<n;i++) leaf[i] = true;
    while(m--)
    {
        int id,k;
        cin >> id >> k;
        leaf[id] = false;
        while(k--)
        {
            int son;
            cin >> son;
            g[id][son] = true;
        }
    }
    vector<int> path;
    path.push_back(w[0]);
    dfs(0,w[0],path);
    sort(res.begin(),res.end(),greater<vector<int>>()); //两个vector<int>自带按照字典序比较
    for(int i=0;i<res.size();i++){
        for(int j=0;j<res[i].size();j++) cout << res[i][j] << " ";
        cout << endl;
    }
    return 0;
    
}

最大的一代

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <cstring>
using namespace std;
const int N = 1100;
int n,m;
int e[N],ne[N],h[N],idx;

void add(int a,int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}

int depth[N];
int max_depth = -1;
void dfs(int u,int d)
{
    if(u==-1) return;
    depth[d]++;
    max_depth = max(max_depth,d);
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j = e[i];
        dfs(j,d+1);
    }
}


int main()
{
    cin >> n >> m;
    memset(h,-1,sizeof h);
    while(m--)
    {
        int father,k;
        cin >> father >> k;
        while(k--){
            int son;
            cin >> son;
            add(father,son);
        }
    }
    dfs(1,1);
    int max_node = -1;
    int level = 1;
    for(int i=1;i<=max_depth;i++){
        if(depth[i] > max_node){
            max_node = depth[i];
            level = i;
        }
    }
    cout << max_node << " " << level << endl;
    return 0;
}

供应链总销售额

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
const int N = 1e5 + 10;
int n;//总节点数
double p,r;  //根节点的初始价格以及每一层节点的溢价
int e[N],ne[N],h[N],idx;
bool leaf[N]; //是否为叶节点
int item_num[N]; //叶节点能够卖的总数量


void add(int a,int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}

double total_sum = 0;
void dfs(int u,double price)
{
    if(leaf[u]){
        total_sum += price * item_num[u];
        return;
    }
    for(int i=h[u];i!=-1;i=ne[i]){
        int j = e[i];
        dfs(j,price*(1+r/100));
    }
}

int main()
{
    cin >> n >> p >> r;
    memset(h,-1,sizeof h);
    for(int i=0;i<n;i++) leaf[i] = false;
    for(int i=0;i<n;i++){
        int k;
        cin >> k;
        if(k==0){
            leaf[i] = true;
            cin >> item_num[i];
        }
        else{
            while(k--){
                int id;
                cin >> id;
                add(i,id);
            }
        }
    }
    dfs(0,p);
    printf("%.1lf",total_sum);
    return 0;
}

供应链最高价格

在这里插入图片描述

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
int n;
double p,r;
int e[N],ne[N],h[N],idx;
bool leaf[N];

void add(int a, int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}

int node_num[N];  //每一层叶子节点的数量
int max_depth = -1;
double cost[N]; //每一层上的节点能出售的价格
void dfs(int u, int d, double price)
{
    if(u==-1) return;
    
    if(leaf[u]){
        max_depth = max(max_depth,d);
        node_num[d]++;
        cost[d] = price;
        return;
    }
    for(int i=h[u];i!=-1;i=ne[i]){
        int j = e[i];
        dfs(j,d+1,price*(1+r/100));
    }
    
}

int main()
{
    memset(h,-1,sizeof h);
    cin >> n >> p >> r;
    int root;
    for(int i=0;i<n;i++){
        int father;
        cin >> father;
        if(father==-1){
            root = i;
        }
        else{
            add(father,i);
        }
    }

    for(int i=0;i<n;i++) leaf[i] = false;
    for(int i=0;i<n;i++){
        if(h[i]==-1) leaf[i] = true;
    }
    dfs(root,1,p);
    printf("%.2lf %d",cost[max_depth],node_num[max_depth]);
    
    return 0;
}

供应链最低价格

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
int n;
double p,r;
int e[N],ne[N],h[N],idx;
bool leaf[N];

void add(int a,int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}


int max_depth = -1;
int node_num[N];
double cost[N];
void dfs(int u,int d,double price)
{
    if(leaf[u]){
        max_depth = d;
        node_num[d]++;
        cost[d] = price;
    }
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j = e[i];
        dfs(j,d+1,price * (1 + r/100));
    }
}

int main()
{
    memset(h,-1,sizeof h);
    cin >> n >> p >> r;
    for(int i=0;i<n;i++) leaf[i] = false;
    for(int i=0;i<n;i++){
        int k;
        cin >> k;
        if(k==0){
            leaf[i] = true;
        }
        else{
            while(k--){
                int son;
                cin >> son;
                add(i,son);
            }
        }
    }
    
    dfs(0,1,p);
    int min_depth = 0;
    for(int i=1;i<=max_depth;i++){
        if(node_num[i]){
            min_depth = i;
            break;
        }
    }
    printf("%.4lf %d",cost[min_depth],node_num[min_depth]);
    return 0;
    
}

堆路径

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1010;
int heap[N];
int n;
vector<vector<int>> res;
vector<int> path;
void dfs(int u)
{
    path.push_back(heap[u]);
    if(2*u > n){ //如果是叶节点的话(只需要看有没有左子树就好了)
        res.push_back(path);
        path.pop_back();
        return;
    }
    if((2*u+1)<=n) dfs(2*u+1);
    if(2*u <= n) dfs(2*u);
    path.pop_back();
}

int main()
{
    cin >> n;
    for(int i=1;i<=n;i++) cin >> heap[i];
    dfs(1);

    for(int i=0;i<res.size();i++){
        cout << res[i][0];
        for(int j=1;j<res[i].size();j++){
            cout << " " <<res[i][j];
        }
        cout << endl;
    }
    
    bool if_max_heap = true;
    bool if_min_heap = true;
    for(int i=0;i<res.size();i++){
        for(int j=1;j<res[i].size();j++){
            if(res[i][j] < res[i][j-1]){
                if_min_heap = false;
                break;
            }
        }

    }
    for(int i=0;i<res.size();i++){
        for(int j=1;j<res[i].size();j++){
            if(res[i][j] > res[i][j-1]){
                if_max_heap = false;
                break;
            }
        }
    }
    if(!if_min_heap && !if_max_heap) cout << "Not Heap" << endl;
    else if(if_min_heap) cout << "Min Heap" << endl;
    else if(if_max_heap) cout << "Max Heap" << endl;
    
    return 0;
}

中缀表达式

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 30;
int n;
bool has_father[N];
string v[N];
int l[N],r[N];
bool leaf[N];
int root;

//如果不是叶节点也不是根节点就需要加括号
vector<string> res;
void dfs(int u)
{
    if(u==0) return;
    
    if(!leaf[u] && u!=root) res.push_back("(");
    dfs(l[u]);
    res.push_back(v[u]);
    dfs(r[u]);
    if(!leaf[u] && u!=root) res.push_back(")");

}

int main()
{
    cin >> n;
    for(int i=1;i<=n;i++){
        cin >> v[i];
        int a,b;
        cin >> a >> b;
        if(a==-1 && b==-1) leaf[i] = true;
        if(a!=-1){
            l[i] = a;
            has_father[a] = true;
        }
        if(b!=-1){
            r[i] = b;
            has_father[b] = true;
        }
    }

    for(int i=1;i<=n;i++){
        if(!has_father[i]) root = i;
    }
    dfs(root);
    for(int i=0;i<res.size();i++) cout << res[i];
    
    return 0;
}

最低公共祖先

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
const int N = 10010;
int m,n; //询问的数量,节点的数量
int inorder[N],preorder[N],seq[N];
map<int,int> pos;//pos把一个数影射成0~n-1中的一个下标值
                 //seq[下标值] = 实际值
int parent[N];  //存i号节点的父节点是谁
int depth[N];  //存i号节点在第几层
int build(int inl,int inr,int prel,int prer,int d)
{
    int root = preorder[prel];
    depth[root] = d;
    int k = root;  //根节点在中序遍历中的位置,i号节点在位置i上
    
    if(inl < k) parent[build(inl,k-1,prel+1,prel+1+k-1-inl,d+1)] = root;
    if(inr > k) parent[build(k+1,inr,prer-(inr-k-1),prer,d+1)] = root;
    return root;
}

int main()
{
    cin >> m >> n;
    for(int i=0;i<n;i++){
        cin >> preorder[i];
        seq[i] = preorder[i];
    }
    sort(seq,seq+n);
    //seq中存的是中序遍历的实际值
    //inorder中存的是中序遍历的下标值
    for(int i=0;i<n;i++){
        inorder[i] = i;
        pos[seq[i]] = i;
    }
    for(int i=0;i<n;i++) preorder[i] = pos[preorder[i]];
    
    int root = build(0,n-1,0,n-1,0);

    //parent[root]=0这不用管,因为走到root后再走一步他的parent是0相当于原地踏步不会影响结果
    
    while (m -- )
    {
        int a, b;
        cin >> a >> b;

        if (pos.count(a) && pos.count(b))
        {
            a = pos[a], b = pos[b];
            int x = a, y = b;

            while (a != b)
                if (depth[a] < depth[b]) b = parent[b];
                else a = parent[a];

            if (a != x && a != y) printf("LCA of %d and %d is %d.\n", seq[x], seq[y], seq[a]);
            else if (a == x) printf("%d is an ancestor of %d.\n", seq[x], seq[y]);
            else printf("%d is an ancestor of %d.\n", seq[y], seq[x]);
        }
        else if (pos.count(a) == 0 && pos.count(b) == 0)
            printf("ERROR: %d and %d are not found.\n", a, b);
        else if (pos.count(a) == 0)
            printf("ERROR: %d is not found.\n", a);
        else
            printf("ERROR: %d is not found.\n", b);
    }


  
    return 0;
}

二叉树中的最低公共祖先

在这里插入图片描述

#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
const int N = 10010;
int m,n;
int preorder[N],inorder[N],seq[N];
map<int,int> pos;

int depth[N],parent[N];
int build(int inl,int inr,int prel,int prer,int d)
{
    int root = preorder[prel];
    int k = root; //这里preorder[i]值为多少就是在中序遍历中的哪个位置
    
    depth[root] = d;
    if(inl < k) parent[build(inl,k-1,prel+1,prel+1+k-1-inl,d+1)] = root;
    if(inr > k) parent[build(k+1,inr,prer-(inr-k-1),prer,d+1)] = root;
    return root;
}

int main()
{
    cin >> m >> n;
    for(int i=0;i<n;i++){
        cin >> inorder[i];
        seq[i] = inorder[i];
        pos[inorder[i]] = i;
        inorder[i] = i;
    }
    for(int i=0;i<n;i++){
        cin >> preorder[i];
        preorder[i] = pos[preorder[i]];
    }
    int root = build(0,n-1,0,n-1,0); 
    while(m--)
    {
        int u,v;
        cin >> u >> v;
        if(pos.count(u) && pos.count(v))
        {
            int x = pos[u],y = pos[v];
            int a = x, b = y;
            while(x != y){
                if(depth[x] < depth[y]) y = parent[y];
                else x = parent[x];
            }
            if(x!=a && x!=b) printf("LCA of %d and %d is %d.\n",u,v,seq[x]);
            else if(x==a) printf("%d is an ancestor of %d.\n",u,v);
            else printf("%d is an ancestor of %d.\n",v,u);
        }
        else if(pos.count(u) && pos.count(v)==0) printf("ERROR: %d is not found.\n",v);
        else if(pos.count(u)==0 && pos.count(v)) printf("ERROR: %d is not found.\n",u);
        else printf("ERROR: %d and %d are not found.\n",u,v);
    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新城里的旧少年^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值