[leetcode 5406] 收集树上所有苹果的最少时间

题目描述

在这里插入图片描述
在这里插入图片描述

分析

这是一个n个节点的无向树,我们可以看成一个无向图的形式,先将所有的边构成一个图,注意是无向图,所以在生成图的时候一条边可以有两条路径,从0-->1 和 1-->0

当我们按照先序遍历的时候,我们无法确定哪一个根节点是路径需要经过的点。所以需要先找到这个有苹果的节点,然后从这个节点逆向走到根节点,中间记录一下那些点走过了,因为题目中是可以攒苹果然后一起带着走到根节点的。

如果是中序遍历的话,则需要模拟一棵树的结构,就不需要无向图了。

后序遍历与邻接表存储

class Solution {
public:
    int ans = 0;//路径中的点的数量,不包括根节点
    int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
        vector<vector<int> > map(n);
        for(auto& e : edges)
        {
            map[e[0]].push_back(e[1]);
            map[e[1]].push_back(e[0]);
        }

        vector<bool> visit(n);
        //后序遍历找到需要经过的节点数
        PostOrder(map,0,hasApple,visit);
        //防止树中没有苹果
        return max(ans,0) * 2;
    }

    bool PostOrder(vector<vector<int> >& map,int index,vector<bool>& hasApple,vector<bool>& visit)
    {
    	//先标记当前节点
        visit[index] = true;
        //记录当前节点是否是需要经过的
        bool flag = hasApple[index];
		//遍历孩子节点
        for(auto son : map[index])
        {
            if(visit[son]) continue;
			//判断这个孩子节点是否是需要经过的节点,采用后序的思想
            if(PostOrder(map,son,hasApple,visit))
            {
                flag = true;
                ans++;
            }
        }
        return flag;
    }    
};

链式存储,参考大佬程序完善后

class Solution {
public:
    struct edge
    {
        int to;
        int next;
    };
    
    edge e[200005];//存放每一条边
    int head[200005];//边的开始节点的位置
    int f[200005];//当前点的父亲节点位置
    int ans = 0;
    
    //链式添加一条边
    void add(int from,int to,int len)
    {
        e[len].to = to;
        e[len].next = head[from];
        head[from] = len;
    }
    
    //搜索,找出需要经过的点,包括根节点
    void dfs(vector<int>& visit,int x)
    {
        //遍历以当前点为起点,可以达到的所有边
        for(int i = head[x]; i; i = e[i].next)
            if(e[i].to != f[x])//并查集,防止重复搜索
            {
                f[e[i].to] = x;
                dfs(visit,e[i].to);
                visit[x] += visit[e[i].to];
            }
        
        //记录可以到达的点
        if(visit[x]) ans++;
    }
    
    int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
        int len = 0;
        for(auto& eoch : edges)
        {
            add(eoch[1],eoch[0],len++);
            add(eoch[0],eoch[1],len++);
        }
            
        vector<int> visit(200005);
        for(int i = 0; i < n; i++)
            visit[i]= hasApple[i];
        
        dfs(visit,0);
        
        return max(ans,1)*2 - 2;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值