蓝桥杯AIGO-4结点选择

来源:互联网 发布:淘宝注册需要打电话吗 编辑:程序博客网 时间:2024/05/21 09:55


输入的树可以被看做一个无环连通图,从任意一点(一般用 1 号结点)发起深度优先遍历(树的后根遍历),在计算权值和的时候应该把父节点的权值应该和子节点的子节点(即孙结点)的权值加和,而子节点的权值应该和它的孙结点加和。所以,一个结点处应该存储两个权值,一个是含有这个结点的权值和,一个是不含有这个结点的权值和,我用一个100005*2的二维数组cost来存储这些信息;用长度为100005的一维数组visited来标志一个结点是否已经访问过,用vector<vector<int>>tree对这棵树进行邻接表存储。用递归实现整个算法。

对所给示例的算法执行过程如下:

先将visited数组初始化为false,表示任何一个结点都没有被访问过。将cost的第0列初始化为相应点的权值,在算法执行结果中表示该节点与孙结点权值的加和,第1列初始化为0,在算法执行结果中表示其子结点和这个子节点的孙结点的权值加和。


先遍历1号结点,发现一号结点有两个儿子,遍历2号,发现2号也有两个儿子。

再遍历4号结点,发现这是一个叶节点,不做任何改变,递归函数直接返回到2号结点处,cost[2][1]+=max(cost[4][1],cost[4][0]),cost[2][0]+=cost[4][1],遍历5号结点时也做同样的操作,得到的cost数组中cost[2][1]变成9,其它不变。

递归函数返回到1号结点处,cost[1][1]+=max(cost[2][1],cost[2][0]),cost[1][0]+=cost[2][1],得到的cost数组如下:


遍历3号结点,发现3号结点没有儿子,不做任何改变,递归函数直接返回到1号结点处cost[1][1]+=max(cost[3][1],cost[3][0]),cost[1][0]+=cost[3][1],得到的cost数组如下:


所有点均已遍历到,算法执行完毕,输出max(cost[1][1],cost[1][0])即为最终结果。

C++代码如下:

#include <bits/stdc++.h>using namespace std;bool visited[100005];int cost[100005][2];vector<vector<int> >tree;void dfs(int v){    visited[v]=true;    for(int i=0;i<tree[v].size();++i)    {        int k=tree[v][i];        if(!visited[k])        {            dfs(k);            cost[v][1]+=max(cost[k][0],cost[k][1]);            cost[v][0]+=cost[k][1];        }    }}int main(int argc, char *argv[]){    int n;    cin>>n;    for(int i=1;i<n+1;++i)    {        cin>>cost[i][0];        vector<int>v;        tree.push_back(v);    }    vector<int>v;    tree.push_back(v);    for(int i=0;i<n-1;++i)    {        int a,b;        cin>>a>>b;        tree[a].push_back(b);        tree[b].push_back(a);    }    dfs(1);    cout<<max(cost[1][0],cost[1][1])<<endl;    return 0;}






原创粉丝点击