大模拟题:
思路:
1.初始化root为1
2.w数组储存每次得到的w&值
3.更新w数组 遍历每个节点的时候将visited数组+1 表示当前已经遍历到第几轮了(用来计算最优解点的时候排除不是的结点)
4.w数组储存每次得到的w&值
5.根据w&的值判断当前保留树的哪一部分
如果保留当前部分(将根节点设为当前节点)
否则将visited[node]数组的值设为-1(更新w数组的时候不访问)
6.更新root为当前最优结点
屎山代码:
#include<bits/stdc++.h>
using namespace std;
int n, m;
struct node {
int w;//权重
vector<int> child;
int parent;
}tree[2002];
int w[2002];//每个节点的总权重
bool flag[2002] = { true };
//计算整棵树每个结点的权重 返回权重
int Compute(int root){
//如果已经不属于
if (!flag[root]) return 0;
w[root] = tree[root].w;
if (tree[root].child.size() == 0) {
return w[root];
}
for (int c : tree[root].child) {
w[root] += Compute(c);
}
return w[root];
}
//计算当前的权值绝对值
vector<int> Compute_W(int root) {
//初始化总权重数组
fill(w, w + 2002, 0);
Compute(root);
vector<int> ww(n + 1, INT_MAX);
for (int i = 1; i <= n; i++) {
ww[i] = abs(w[i]-(w[root]-w[i]));
}
return ww;
}
void pprint(vector<int> num) {
for (int i = 0; i < num.size(); i++) {
cout << num[i] << " ";
}
cout << endl;
}
bool isAncestor(int now, int ancestor) {
if (now == -1)
return false;
if (now == ancestor)
return true;
return isAncestor(tree[now].parent, ancestor);
}
//表示失效
void dfs(int root) {
flag[root] = false;
if (tree[root].child.size() == 0)
return;
for (int c : tree[root].child)
dfs(c);
}
//计算当前有效节点个数
int count_num() {
int num = 0;
for (int i = 1; i <= n; i++) {
if (flag[i] == true)
num++;
}
return num;
}
//输出若干整数 代表现在问是否属于这个类别
void solve(int c) {
//初始化根节点
int root = 1;
//初始化标记
fill(flag, flag + 2002, true);
//初始化总权重数组
fill(w, w + 2002, 0);
while (1) {
//初始化排序好的数组绝对值差
vector<int> now_w = Compute_W(root);
//计算当前的最小绝对值
int min_index;
int min = INT_MAX;
for (int i = 1; i <= n; i++) {
if (now_w[i] < min) {
min_index = i;
min = now_w[i];
}
}
//询问c类别是否属于当前类别
cout << min_index;
if (isAncestor(c, min_index)) {
root = min_index;
//该结点的以外的子树标记为失效
if (tree[min_index].parent != -1) {
flag[tree[min_index].parent] = false;
for (int c : tree[tree[min_index].parent].child) {
if (c != min_index)
dfs(c);
}
}
}
else {
root = tree[min_index].parent;
//该结点的子树标记为失效
dfs(min_index);
}
if (count_num() == 1) {
cout << endl;
break;
}
else {
cout << " ";
}
}
}
int main() {
//n:全部类别的数量
//m:需要测试的类别数量
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin>>tree[i].w;//权重
}
//特殊标记
tree[1].parent = -1;
for (int i = 1; i < n; i++) {
int son = i + 1;
int parent;
cin >> parent;
tree[parent].child.push_back(son);
tree[son].parent = parent;
}
for (int i = 0; i < m; i++) {
//任务是被归类到该类别的名词 需要提出怎么样最少的问题
int c;
cin >> c;
solve(c);
}
return 0;
}