第32次CCF认证-树上搜索

1. 题意描述

在这里插入图片描述

2. 输入样例

在这里插入图片描述

3. 思路

按照题意模拟,然后注意longlong,和模拟的过程。
其实可以得出一些技巧,比如你可以先把伪代码写出来,然后再进行变成,这样可以理解清楚思路,加快速度。

4. 代码

#include <bits/stdc++.h>

using namespace std;
#define ll long long
const int N = 2e3+10;
int w[N];
int fa[N];
ll sze[N];
int sons[N];
ll w_min = N+1,w_M = LONG_MAX;
vector<int> son[N];
int vis[N];
int cnt;
ll sum;
void dfs(int root) 
{
    if (vis[root] == 0) {sze[root] = 0;sons[root] = 0;return;}
    sze[root] = w[root];
    sons[root] = 1;
    sum += w[root];
    for (int i = 0;i < son[root].size();i ++) {
        dfs(son[root][i]);
        sze[root] += sze[son[root][i]];
        sons[root] += sons[son[root][i]];
    }
}

void dfs2(int root)
{
    if (vis[root] == 0) return;

    ll tmp = abs(sum - sze[root]*2);
    // cout<<root<<":"<<tmp<<endl;
    if (tmp < w_M) {
        w_M = tmp;w_min = root;
    } 
    if (tmp == w_M&&w_min>root) 
        w_min = root;
    for (int i = 0;i < son[root].size();i ++) {
        dfs2(son[root][i]);
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("a.txt","r",stdin);
        freopen("aout.txt","w",stdout);
    #endif
    int n,m;cin>>n>>m;
    for (int i = 1;i <= n;i ++) cin>>w[i];
    for (int i = 1;i < n;i ++) 
    {
        int x;cin>>x;
        fa[i+1] = x;
        son[x].push_back(i+1);
    }
    while (m --) {
        int x;cin>>x;
        int root = 1;
        for (int i = 1;i <= n;i ++) vis[i] = 1;
        cnt = n;
        while (cnt > 1) {
            sum = 0,w_M = LONG_MAX,w_min = N+1;
            dfs(root);
            dfs2(root);
            int tx = x;
            cout<<w_min<<" ";
            while (tx != root&&tx != w_min) tx = fa[tx];
            if (tx == root) {
                cnt -= sons[w_min];root = root;
                vis[w_min] = 0;
            } else {
                root = w_min;
                cnt = sons[w_min];
            }
        }cout<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

疯狂的码泰君

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

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

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

打赏作者

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

抵扣说明:

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

余额充值