五月集训(第27天)—图

1. 1791. 找出星型图的中心节点

    思路:
        每条边都会连接中心结点,所以一条边的起点或者终点是中心结点。

class Solution {
public:
    int findCenter(vector<vector<int>>& edges) {
        int a = edges[0][0];
        if (a == edges[1][0] || a == edges[1][1]) {
            return a;
        }
        return edges[0][1];
    }
};

2. 797. 所有可能的路径

    思路:
        从起点0开始深搜,搜到点n-1保存答案路径,回到上一点再搜,直到找到图上所有到达n-1的路径。

class Solution {
    vector<vector<int>> ans;
    vector<int> temp;

    void dfs(int s, vector<vector<int>> &graph, int n) {
        int m = graph[s].size(), i;
        if (s == n - 1) {   /* 递归出口是搜到点 n - 1 保存答案 */
            ans.push_back(temp);
            return ;
        }

        for (i = 0; i < m; ++i) {   /* 回溯遍历 */
            temp.push_back(graph[s][i]);
            dfs(graph[s][i], graph, n);
            temp.pop_back();
        }
    }
public:
    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
        int graph_size = graph.size();
        ans.clear();
        temp.clear();
        temp.push_back(0);
        dfs(0, graph, graph_size);
        return ans;
    }
};

3. 851. 喧闹和富有

    思路:
        利用richer数组建图:从一个人指向比自己富的人。
        从每个人出发,遍历每个可达结点,即比自己富的人,记录quiet最小的人为答案。(起始值设为自己)
        注意:每次从一个人出发,利用hash[]标记遍历过的结点,如果dfs中发现遍历过的结点,则直接返回。按理说n<=500且没有环,应该不会超时,但是不加hash[]就TLE,不理解,QAQ

class Solution {
    int hash[501];
    void dfs(int s, vector<vector<int>> &graph, vector<int> &ans, vector<int> &quiet, int pos_s) {
        if (hash[s]) return;
        hash[s] = 1;
        int m = graph[s].size(), i;
        if (m == 0) return ;
        for (i = 0; i < m; ++i) {
            if ( quiet[ graph[s][i] ] < quiet[ ans[pos_s] ] ) {
                ans[pos_s] = graph[s][i];
            }
            dfs(graph[s][i], graph, ans, quiet, pos_s);
        }
    }
public:
    vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {
        vector<int> ans;
        int n = quiet.size();
        int richer_size = richer.size(), i;
        vector<vector<int>> graph (n);
        for (i = 0; i < n; ++i) ans.push_back(i);

        for (i = 0; i < richer_size; ++i) {
            graph[richer[i][1]].push_back(richer[i][0]);
        }

        for (i = 0; i < n; ++i) {
            memset(hash, 0, sizeof(hash));
            dfs(i, graph, ans, quiet, i);
        }
        return ans;
    }
};

4. 959. 由斜杠划分区域

    思路:
        两中方向的斜杠可以把一个方格划分为0,1,2,3四个区域,利用并查集对区域进行操作即可得连通块得数目。
        每个方块向右将当前方块1区右边方块3区连通
        每个方块向下将当前方块3区下边方块0区连通
        '/'将每个方块内的0区3区1区2区连通
        '\\'将每个方块内的0区1区2区3区连通
        ' '将每个方块内的0区,1区****2区,3区全部连通
在这里插入图片描述


class Solution {
    // 将一个方格分为上下左右四个三角形,并把二维网络压成一维,数组长度为 4 * n * n
    #define N 3610
    int F[N];
    int count;

    void union_find_init(int n) {
        int len = 4 * n * n, i;
        count = len;
        for (i = 0; i < len; ++i) F[i] = i;
    }

    void union_set(int a, int b) {
        int fa = find_f(a);
        int fb = find_f(b);
        if (fa == fb) return ;
        F[fa] = fb;
        count--;
    }

    int find_f(int x) {
        if (x == F[x]) return x;
        return F[x] = find_f(F[x]);
    }

public:
    int regionsBySlashes(vector<string>& grid) {
        int n = grid.size();
        union_find_init(n);
        int index = 0, i, j;

        for (i = 0; i < n; ++i) {
            for (j = 0; j < n; ++j) {
                int rect = i * n + j;
                int rect_right = i * n + j + 1;
                int rect_down = (i + 1) * n + j;
                if (i < n - 1) union_set((rect << 2) | 2, ((rect_down) << 2) | 0);     // 合并上面方格的2和下面方格的0
                if (j < n - 1) union_set((rect << 2) | 1, (rect_right << 2) | 3 );      // 合并左边方格的1和右边方格的3

                if (grid[i][j] == ' ') {            /* 空格则合并四个小三角 */
                    union_set((rect << 2) | 0, (rect << 2) | 1);
                    union_set((rect << 2) | 0, (rect << 2) | 2);
                    union_set((rect << 2) | 0, (rect << 2) | 3);
                } else if (grid[i][j] == '/') {     /* '/'则合并0,3和1,2区域 */
                    union_set((rect << 2) | 0, (rect << 2) | 3);
                    union_set((rect << 2) | 1, (rect << 2) | 2);
                } else {                            /* '\\'则合并0,1和2,3区域 */
                    union_set((rect << 2) | 0, (rect << 2) | 1);
                    union_set((rect << 2) | 2, (rect << 2) | 3);
                }
            }
        }
        return count;
    }
};

posted @ 2022-06-03 12:04  番茄元  阅读(21)  评论(0)    收藏  举报