5月27日-图-题解

5月27日-图-题解

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

解法1.

计算每个点的度,判断度是否到了n-1,n为点的个数

    int findCenter(vector<vector<int>>& edges) {
        int n=edges.size()+1;
        int point[n+1];
        memset(point,0,sizeof(point));
        for(int i=0;i<n-1;++i){
            if(++point[edges[i][0]]==n-1){
                return edges[i][0];
            }
            if(++point[edges[i][1]]==n-1){
                return edges[i][1];
            }
        }
        return 0;
    }

解法2.

因为中心点必与其余点连接,只需要随便取两对边,判断其中重合的点即为中心点

    int findCenter(vector<vector<int>>& edges) {
        int k=edges[0][0];
        if(k==edges[1][0]||k==edges[1][1]){
            return k;
        }
        return edges[0][1];
    }

797. 所有可能的路径

简单的回溯一下,记录每个走过的节点即可

    List<List<Integer>> ans;
    int n;
    List<Integer> path;

    // index 为当前到达的节点
    void backTracking(int[][] graph, int index) {
        if (index == n) {
            ans.add(new ArrayList<>(path));
            return;
        }
        int[] next = graph[index];
        for (int i = 0; i < next.length; ++i) {
            path.add(next[i]);
            backTracking(graph, next[i]);
            path.remove(path.size() - 1);
        }
    }

    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        n = graph.length - 1;
        ans = new ArrayList<>();
        path = new ArrayList<>();
        path.add(0);
        backTracking(graph, 0);
        return ans;
    }

851. 喧闹和富有

建立反图,对于people X,把所有比X富有的人放一起,进行DFS,这里注意要用到一个hash[u],作用如下

我们假设 1比2富有,3比2富有,而1比3富有,那么我们在计算DFS(3)的时候已经计算过1了,这里就无需重复计算避免超时,所以设定一个hash数组来终止遍历

    vector<int> edges[510];
    int hash[501];
    void dfs(vector<int>& quiet,int u,int &ans){
        if(hash[u]){
            return;
        }
        hash[u]=1;
        if(quiet[u]<quiet[ans]){
            ans=u;
        }
        for(int i=0;i<edges[u].size();++i){
            int v=edges[u][i];
            dfs(quiet,v,ans);
        }
    }
public:
    vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {
        int n=quiet.size();
        for(int i=0;i<n;++i){
            edges[i].clear();
        }
        for(int i=0;i<richer.size();++i){
            edges[richer[i][1]].push_back(richer[i][0]);
        }
        vector<int> ret;
        for(int i=0;i<n;++i){
            memset(hash,0,sizeof(hash));
            int ans=i;
            dfs(quiet,i,ans);
            ret.push_back(ans);
        }
        return ret;
    }

959. 由斜杠划分区域

用到并查集思路,为什么英雄哥的做法里要将一个方块再分为四个呢,就是为了方便统计连通情况,这里盗下英雄哥的图予以说明

对于每个小方块来说,因为要考虑和其他方块的连通情况,所以要进行划分,并有如下几种类型

区域3:不管字符是什么,都会与正下方方块的区域0连通

区域2:不管字符是什么,都会与正右方方块的区域1连通

“/”:区域0,1连通,2,3连通

“\”:区域0,2连通,1,3连通

”空字符“:0,1,2,3均连通

最终,在构造出节点之间的连接关系后,就可以利用并查集求出连通分量的数目了。利用一个hash统计结果即可

代码中的划分是按照顺时针0,1,2,3划分的,注意区别

class Solution {
    #define maxn 4000
    int f[maxn];
    void init(){
        for (int i = 0; i <maxn; i++) {
            f[i] = i;
        }
    }
    int find(int x) {
        return x == f[x] ? (x) : (f[x] = find(f[x]));
    }
    bool merge(int x, int y) {
        int fx = find(x), fy = find(y);
        if (fx != fy) {
            f[fx] = fy;
            return true;
        }
    return false;
    }
public:
    int regionsBySlashes(vector<string>& grid) {
        int n = grid.size();
        init();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int idx = i * n + j;
                if (i < n - 1) {
                    int bottom = idx + n;
                    merge(idx * 4 + 2, bottom * 4);
                }
                if (j < n - 1) {
                    int right = idx + 1;
                    merge(idx * 4 + 1, right * 4 + 3);
                }
                if (grid[i][j] == '/') {
                    merge(idx * 4, idx * 4 + 3);
                    merge(idx * 4 + 1, idx * 4 + 2);
                } else if (grid[i][j] == '\\') {
                    merge(idx * 4, idx * 4 + 1);
                    merge(idx * 4 + 2, idx * 4 + 3);
                } else {
                    merge(idx * 4, idx * 4 + 1);
                    merge(idx * 4 + 1, idx * 4 + 2);
                    merge(idx * 4 + 2, idx * 4 + 3);
                }
            }
        }

        int hash[n*n*4];
        int cnt=0;
        memset(hash,0,sizeof(hash));
        for (int i = 0; i < n * n * 4; i++) {
            int fa = find(i);
            if(!hash[fa]){
                hash[fa]=1;
                ++cnt;
            }
        }
        return cnt;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值