(nice!!!)LeetCode 2065. 最大化一张图中的路径价值(深度优先搜索dfs、图)

2065. 最大化一张图中的路径价值

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

思路:暴力搜索dfs。
1、maxTime<=100且每条边的值最少为10,那么最多可以经历过10条边,也就是11个节点(节点可重复),深搜的深度为11。
2、每个节点至多有四条边,也就是深搜的宽度为4。
3、暴力dfs的时间复杂度最大为0(4^ 11)<0(10^7)
细节看注释

方法一:纯暴力搜索dfs

class Solution {
public:
    typedef pair<int,int> PII;
    int n;
    vector<bool> sta;
    vector<vector<PII>> g;
    //记录最大的价值
    int mx=0;
    //参数:当前的节点、当前总的花费时间、当前总的价值、values、maxTime
    void dfs(int u,int sumTime,int sumVal,vector<int>& values,int maxTime){
    	//只要当前节点为0,就可以更新最大值mx
        if(u==0){
            mx=max(mx,sumVal);
        }
        //能到这步,说明“当前总的花费时间”<=maxTime
        //开始遍历u可以到的其他节点
        for(int i=0;i<g[u].size();i++){
        	//到下一个节点时,花费的时间超过maxTime,就继续遍历
            if(sumTime+g[u][i].second>maxTime){
                continue;
            }
            //可以满足“花费的时间”<=maxTime
            
            int t=g[u][i].first;
            int tmp=sumVal;
            //即将跳的下一个节点没有被遍历过
            if(sta[t]==0){
                tmp=sumVal+values[t];
                sta[t]=1;
                dfs(t,sumTime+g[u][i].second,tmp,values,maxTime);
                sta[t]=0;
            }else{//即将跳的下一个节点有被遍历过
                dfs(t,sumTime+g[u][i].second,tmp,values,maxTime);
            }
            
        }
    }
    int maximalPathQuality(vector<int>& values, vector<vector<int>>& edges, int maxTime) {
   		//节点的个数
        n=values.size();
        //每个节点的遍历状态,避免重复添加同一个节点的价值
        sta=vector<bool>(n,0);
        //构建邻接表
        g=vector<vector<PII>>(n);
        for(int i=0;i<edges.size();i++){
            int x=edges[i][0],y=edges[i][1],val=edges[i][2];
            g[x].push_back({y,val});
            g[y].push_back({x,val});
        }
        //标记0号节点的值已经添加过
        sta[0]=1;
        //参数:当前的节点、当前总的花费时间、当前总的价值、values、maxTime
        dfs(0,0,values[0],values,maxTime);
        return mx;
    }
};

方法二:暴力搜索dfs+剪枝。
剪枝的思路:计算出每个节点到0节点的最短时间,可以改进dfs判断时间是否超时的部分。计算最短时间可以用dijkstra,下面代码用到的是堆优化的dijkstra算法。

class Solution {
public:
    typedef pair<int,int> PII;
    int n;
    vector<bool> sta;
    vector<vector<PII>> g;
    vector<int> dis;
    int mx=0;
    void dfs(int u,int sumTime,int sumVal,vector<int>& values,int maxTime){
        if(u==0){
            mx=max(mx,sumVal);
        }
        for(int i=0;i<g[u].size();i++){
        	//剪枝的地方在这里
            if(sumTime+g[u][i].second+dis[g[u][i].first]>maxTime){
                continue;
            }
            int t=g[u][i].first;
            int tmp=sumVal;
            if(sta[t]==0){
                tmp=sumVal+values[t];
                sta[t]=1;
                dfs(t,sumTime+g[u][i].second,tmp,values,maxTime);
                sta[t]=0;
            }else{
                dfs(t,sumTime+g[u][i].second,tmp,values,maxTime);
            }
            
        }
    }
    int maximalPathQuality(vector<int>& values, vector<vector<int>>& edges, int maxTime) {
        n=values.size();
        sta=vector<bool>(n,0);
        //记录每个节点到0号节点的最短时间
        dis=vector<int> (n,INT_MAX);
        g=vector<vector<PII>>(n);
        for(int i=0;i<edges.size();i++){
            int x=edges[i][0],y=edges[i][1],val=edges[i][2];
            g[x].push_back({y,val});
            g[y].push_back({x,val});
        }
        //计算每个节点到0号节点的最短时间
        dis[0]=0;
        priority_queue<PII,vector<PII>,greater<PII>> qu;
        qu.push({0,0});
        while(qu.size()){
            PII tmp=qu.top();
            qu.pop();
            int  u=tmp.second,val=tmp.first;
            //如果当前的时间val比dis[u]还大的话,说明这个点之前就已经遍历过了
            if(dis[u]<val) continue;

            for(int i=0;i<g[u].size();i++){
                if(val+g[u][i].second<dis[g[u][i].first]){
                    dis[g[u][i].first]=val+g[u][i].second;
                    qu.push({val+g[u][i].second,g[u][i].first});
                }
            }
        }
        sta[0]=1;
        dfs(0,0,values[0],values,maxTime);
        return mx;
    }
};
  • 11
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值