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;
}
};