算法第四版- 4.1

算法第四版- 4.1

无向图

1.单点连通性

LC面试题04.01节点间通路

 class Solution {
public:
    vector<unordered_set<int>> edge;  //记录有向边,不能用并查集
    unordered_set<int> visited;  //是否访问过
    bool dfs(int cur, int target) {
        if(visited.count(cur)) return false;
        visited.insert(cur);
        if(cur == target) return true;
        for(auto v : edge[cur]) {
            if(dfs(v, target))
                return true;
        }
        return false;
    }
    bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
        edge.resize(n);
        for(auto &e : graph)
            edge[e[0]].insert(e[1]);
        return dfs(start, target);
    }
};

不过下面这种写法更加原生态的dfs,从结尾往前搜。

class Solution {
public:
    bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
        if(start == target) return true;
        for(auto& e : graph)
            if(e[1] == target)
                return findWhetherExistsPath(n,graph,start,e[0]);
        return false;
    }
}

2.单点路径

LC剑指offer110,所有路径
很经典的dfs回溯。

  class Solution {
public:

    vector<vector<int>> ans;
    vector<int> stk;

    void dfs(vector<vector<int>>& graph, int x, int n) {
        if (x == n) {
            ans.push_back(stk);
            return;
        }
        for (auto& y : graph[x]) {
            stk.push_back(y);
            dfs(graph, y, n);
            stk.pop_back();
        }
    }

    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
        stk.push_back(0);
        dfs(graph, 0, graph.size() - 1);
        return ans;
    }
};

3.单点最短路径

最短路径大小
把上面这道题目看一看
然后输入输出为:
在这里插入图片描述
代码为:

#include <iostream>
#include <queue>
using namespace std;
static const int N = 100;
static const int INFTY = (1 << 21);  //最大值
int n, M[N][N];
int d[N];
void bfs(int s) {
    queue<int>q;
    q.push(s);
    for (int i = 0; i < n; i++) d[i] = INFTY;
    d[s] = 0;
    int u;
    while (!q.empty()) {
        u = q.front();
        q.pop();
        for (int v = 0; v < n; v++) {
            if (M[u][v] == 0) continue;
            if (d[v] != INFTY) continue;
            d[v] = d[u] + 1;
            q.push(v);
        }
    }
    for (int i = 0; i < n; i++) {
        cout << i + 1 << " " << ((d[i] == INFTY) ? (-1) : d[i]) << endl;
    }
}
int main()
{
    cout << "输入\n";
    int u, k, v;
    cin >> n;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            M[i][j] = 0;
    }
    for (int i = 0; i < n; i++) {
        cin >> u >> k;
        u--;
        for (int j = 0; j < k; j++) {
            cin >> v;
            v--;
            M[u][v] = 1;
        }
    }
    cout << "输出:\n";
    bfs(0);
    return 0;
}

代码是《挑战程序设计竞赛2》上P236.
关于最短路径,还有Dijkstra,Floyd,Spfa,Ford
BFS只能适用于无权图,即权值为1
重翻白书,感觉受益良多,半年前看的了。不知道等大三校招的时候能不能把这本书全学会。感觉大四毕业也可能不会。

4.连通性/连通分量

连通分量其实就是岛屿数量
还是比较推荐用并查集。
并查集求岛屿数量

5.检测环

这个课本上的代码是错的。。。
首先可以肯定这是有向图的东西。(因为我在测试中改变边的方向,输出答案变化了。所以肯定不是无向图)
但是针对一些特殊的图,又跑不出正确结果。我可以勘误了。。。

6.双色问题(图的二分性)

LC785判断二分图
染色,记忆化递归

class Solution {
public:
 bool dfs(const vector<vector<int>> &g, int i, int c, vector<int> &v) {      //返回第i个点染c色能否成功
        if (v[i] != -1) return v[i] == c;                                       //第i个点已染过
        v[i] = c;                                                               //对第i个点染上c色
        for (int j : g[i]) if (!dfs(g, j, !c, v)) return false;                 //递归相邻的点,c => !c 换色
        return true;
    }
    bool isBipartite(vector<vector<int>>& graph) {
        const int n = graph.size();
        vector<int> v(n, -1);                                                   //-1表示待染色
        for (int i = 0; i < n; i++) if (v[i] == -1 && !dfs(graph, i, 0, v)) return false;
        return true;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值