图的DFS

LeetCode2368 受限条件下可到达节点的数目

class Solution {
public:
    int dfs(vector<vector<int>>& g,int x,int fa){
        int sum=1;
        for(int y:g[x]){
            if(y!=fa) sum+=dfs(g,y,x);
        }
        return sum;
    }
    int reachableNodes(int n, vector<vector<int>>& edges, vector<int>& restricted) {
        vector<vector<int>> g(n);
        unordered_set<int> s;
        for(int i=0;i<restricted.size();i++) s.insert(restricted[i]);
        for(int i=0;i<edges.size();i++){
            int x=edges[i][0],y=edges[i][1];
            if(!s.count(x)&&!s.count(y)){//两节点都不受限才建立边
                g[x].push_back(y);
                g[y].push_back(x);
            }
        }
        return dfs(g,0,-1);
    }
};

时间复杂度:O(n)

空间复杂度:O(n) 

LeetCode2477 到达首都的最少油耗(贡献法)

 

/*
 * @lc app=leetcode.cn id=2477 lang=cpp
 *
 * [2477] 到达首都的最少油耗
 */

// @lc code=start
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

class Solution {
public:
    long long res=0;
    int sum=0;
    int dfs(vector<vector<int>>& g,int x,int fa,int seats){
        int sum=1;
        for(int y:g[x]){
            if(y!=fa){ //递归子节点,不能递归父节点
                sum+=dfs(g,y,x,seats); //统计子树大小
            }
        }
        if(x!=0) //x不是根节点
            res+=(sum-1)/seats+1; //ceil(sum*1.0/seats); 
        return sum;
    }
    long long minimumFuelCost(vector<vector<int>>& roads, int seats) {
        int n=roads.size()+1;
        vector<vector<int>> g(n);
        for(int i=0;i<roads.size();i++){
            int from=roads[i][0],to=roads[i][1];
            g[from].push_back(to);
            g[to].push_back(from);
        }
        dfs(g,0,-1,seats);
        return res;
    }
};

时间复杂度:O(n)

空间复杂度:O(n) 

LeetCode924 尽量减少恶意软件的传播

 

class Solution {
public:
    int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
        int n=graph.size();
        vector<int> ids(n,0); //ids[i]表示节点i所在的连通分量
        unordered_map<int,int> id_size; //连通分量id, 大小
        int id=1;
        int size;
        function<void(int)> dfs=[&](int x){
            size++;
            ids[x]=id;
            for(int y=0;y<n;y++){
                if(ids[y]==0&&graph[x][y]==1){
                    dfs(y);
                }
            }
        };
        for(int i=0;i<n;i++){
            if(ids[i]==0){ //该节点未被访问过
                size=0;
                dfs(i);
                id_size[id]=size;
                id++;
            }
        }
        int m=initial.size();
        vector<int> sum(n,0); //sum[i]表示将节点i从已感染节点中删除,能够减少的感染节点数
        for(int i=0;i<m;i++){
            sum[initial[i]]=id_size[ids[initial[i]]];
        }
        for(int i=0;i<m;i++){//如果已感染节点x,y在同一连通分量中,sum[x]=0,sum[y]=0
            for(int j=i+1;j<m;j++){
                int x=initial[i],y=initial[j];
                if(ids[x]==ids[y]){
                    sum[x]=0;
                    sum[y]=0;
                }
            }
        }
        int res=initial[0];
        for(int i=0;i<m;i++){
            int x=initial[i];
            if(sum[x]>sum[res]||sum[x]==sum[res]&&x<res) res=x;
        }
        return res;
    }
};

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值