目录
题意分析
这道题其实就是找邻居里顶点值最小的。一个很直观的想法就是dfs搜索,又由于存在“富有”关系,也就是有向无环图,所以遍历搜索时也可以采用拓扑排序的方法解决。
算法思路
参考了题解,发现写的比我的屎山好多了。
两个方法都要先建立好邻接表,所以就不重复了,这是每个图题的必须操作。这里只提下关键思路。
一、dfs搜索
要求最小的顶点值,一种可能就是本身最小,一种就是我的邻接表内的点的顶点值最小,所以可以深搜来解决。注意到搜索有些搜索情况是重复的,为了提高效率我们要做个记忆化。所以
- 创立记忆数组,记录遍历结果
- 如果顶点没遍历过,将记忆数组初始化为当前顶点的值
- 遍历该顶点的邻接点,如果临接点更小,更新
- 返回结果,输出
二、拓扑排序
也就将入度为0的顶点先遍历输出即可,不过注意此处图存储顺序反了,因为要找富人里最安静的,所以最富有的人就不需要遍历了。
- 创建入度数组
- 创建队列,将入度为0的顶点入队
- 弹出顶点,因为入度为0,所以如果邻居比它的值大,更新邻居就可以了。
- 队列为空,结束输出。
代码实现
dfs
class Solution {
public:
vector<vector<int>> g;
vector<int> ans;
vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {
int n=richer.size(),m=quiet.size();
g.resize(m);
ans.resize(m,-1);
for(auto & r:richer){
g[r[1]].emplace_back(r[0]);
}
for(int i=0;i<m;i++){
dfs(i,quiet);
}
return ans;
}
void dfs(int cur,vector<int>&quiet){
if(ans[cur]!=-1) return ;
ans[cur]=cur;
for(auto & nxt:g[cur]){
dfs(nxt,quiet);
if(quiet[ans[nxt]]<quiet[ans[cur]]){
ans[cur]=ans[nxt];
}
}
}
};
拓扑
class Solution {
public:
vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {
int m=quiet.size();
vector<vector<int>> g(m);
vector<int> indegree(m,0);
for(auto & r:richer){
g[r[0]].emplace_back(r[1]);
indegree[r[1]]++;
}
queue<int> q;
for(int i=0;i<m;i++){
if(indegree[i]==0) q.emplace(i);
}
vector<int> ans(m);
iota(ans.begin(),ans.end(),0);//连续编号函数
while(!q.empty()){
int cur=q.front();q.pop();
for(auto & nxt:g[cur]){
if(quiet[ans[nxt]]>quiet[ans[cur]]){
ans[nxt]=ans[cur];
}
if(--indegree[nxt]==0) q.emplace(nxt);
}
}
return ans;
}
};
总结
这题是一道图的遍历问题,也比较经典吧,2个方法值得多理解。