• leetcode1568 使陆地分离的最少天数


    思路:

    容易发现答案只能是0,1或2,因此可以暴力枚举。另外,还可以重新构图之后使用tarjan算法寻找割点来判断,注意tarjan算法中是如何判断根节点是否是割点的。参考:https://www.cnblogs.com/nullzx/p/7968110.html。 

    实现1:

     1 class Solution
     2 {
     3 public:
     4     const int dx[4] = {1, 0, -1, 0};
     5     const int dy[4] = {0, 1, 0, -1};
     6     void dfs(int x, int y, vector<vector<int>>& grid, vector<vector<int>>& vis)
     7     {
     8         int n = grid.size(), m = grid[0].size();
     9         vis[x][y] = 1;
    10         for (int i = 0; i < 4; i++)
    11         {
    12             int nx = x + dx[i];
    13             int ny = y + dy[i];
    14             if (nx >= 0 && nx < n && ny >= 0 && ny < m && grid[nx][ny] == 1 && !vis[nx][ny])
    15             {
    16                 dfs(nx, ny, grid, vis);
    17             }
    18         }
    19     }
    20     int count_connected_components(vector<vector<int>>& grid)
    21     {
    22         int n = grid.size(), m = grid[0].size();
    23         vector<vector<int>> vis(n, vector<int>(m, 0));
    24         int cnt = 0;
    25         for (int i = 0; i < n; i++)
    26         {
    27             for (int j = 0; j < m; j++)
    28             {
    29                 if (!vis[i][j] && grid[i][j] == 1)
    30                 {
    31                     cnt++;
    32                     dfs(i, j, grid, vis);
    33                 }
    34             }
    35         }
    36         return cnt;
    37     }
    38     bool check(vector<vector<int>>& grid)
    39     {
    40         int cccnt = count_connected_components(grid);
    41         return cccnt >= 2 or cccnt == 0; 
    42     }
    43     int minDays(vector<vector<int>>& grid)
    44     {
    45         if (check(grid)) return 0;
    46         int n = grid.size(), m = grid[0].size();
    47         for (int i = 0; i < n; i++)
    48         {
    49             for (int j = 0; j < m; j++)
    50             {
    51                 if (grid[i][j] == 1)
    52                 {
    53                     grid[i][j] = 0;
    54                     if (check(grid)) return 1;
    55                     grid[i][j] = 1;
    56                 }
    57             }
    58         }
    59         return 2;
    60     }
    61 };

    实现2:

      1 class TarjanSCC
      2 {
      3 private:
      4     const vector<vector<int>>& edges;
      5     vector<int> low, dfn, fa;
      6     int timestamp = -1;
      7     int n;
      8     
      9 private:
     10     // Tarjan 算法求解割点模板
     11     void getCuttingVertex(int u, int parent, vector<int>& ans)
     12     {
     13         low[u] = dfn[u] = ++timestamp;
     14         fa[u] = parent;
     15         int child = 0;
     16         bool iscv = false;
     17         for (int v: edges[u])
     18         {
     19             if (dfn[v] == -1)
     20             {
     21                 ++child;
     22                 getCuttingVertex(v, u, ans);
     23                 low[u] = min(low[u], low[v]);
     24                 if (!iscv && parent != -1 && low[v] >= dfn[u])
     25                 {
     26                     ans.push_back(u);
     27                     iscv = true;
     28                 }
     29             }
     30             else if (v != fa[u]) low[u] = min(low[u], dfn[v]);
     31         }
     32         if (!iscv && parent == -1 && child >= 2) ans.push_back(u);
     33     }
     34 
     35 public:
     36     TarjanSCC(const vector<vector<int>>& _edges): edges(_edges), n(_edges.size()) {}
     37 
     38     int check()
     39     {
     40         low.assign(n, -1);
     41         dfn.assign(n, -1);
     42         fa.assign(n, -1);
     43         timestamp = -1;
     44         
     45         // cutting vertices 存储割点
     46         vector<int> cvs;
     47         // connected components count 存储连通分量个数
     48         int cccnt = 0;
     49         for (int i = 0; i < n; ++i)
     50         {
     51             if (dfn[i] == -1)
     52             {
     53                 ++cccnt;
     54                 getCuttingVertex(i, -1, cvs);
     55             }
     56         }
     57         // 如果连通分量个数大于 1,答案为 0
     58         if (cccnt > 1) return 0;
     59         // 如果存在割点,答案为 1
     60         if (!cvs.empty()) return 1;
     61         return 2;
     62     }
     63 };
     64 
     65 class Solution
     66 {
     67 private:
     68     static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
     69 
     70 public:
     71     int minDays(vector<vector<int>>& grid)
     72     {
     73         int m = grid.size();
     74         int n = grid[0].size();
     75         
     76         // 节点重标号
     77         int landCount = 0;
     78         unordered_map<int, int> relabel;
     79         for (int i = 0; i < m; ++i)
     80         {
     81             for (int j = 0; j < n; ++j)
     82             {
     83                 if (grid[i][j] == 1)
     84                 {
     85                     relabel[i * n + j] = landCount;
     86                     ++landCount;
     87                 }
     88             }
     89         }
     90         if (landCount <= 1) return landCount;
     91 
     92         // 添加图中的边
     93         vector<vector<int>> edges(landCount);
     94         for (int i = 0; i < m; ++i)
     95         {
     96             for (int j = 0; j < n; ++j)
     97             {
     98                 if (grid[i][j] == 1)
     99                 {
    100                     for (int d = 0; d < 4; ++d)
    101                     {
    102                         int ni = i + dirs[d][0];
    103                         int nj = j + dirs[d][1];
    104                         if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == 1)
    105                         {
    106                             edges[relabel[i * n + j]].push_back(relabel[ni * n + nj]);
    107                         }
    108                     }
    109                 }
    110             }
    111         }
    112 
    113         auto scc = TarjanSCC(edges);
    114         return scc.check();
    115     }
    116 };
  • 相关阅读:
    U盘复制文件到最后5秒会卡住怎么办解决
    解决PuTTY中文乱码
    NSA Fuzzbunch中EternalRomance工具复现过程
    VirtualBox修改现有VDI虚拟磁盘大小
    高危Windows系统 SMB/RDP远程命令执行漏洞 手工修复办法
    数据库页已标记为 RestorePending,可能表明磁盘已损坏。要从此状态恢复,请执行还原操作。
    用Partimage创建或恢复分区备份
    IIS7保存配置文件及导入、导出、备份、还原
    WINDOWS SERVER 2008远程桌面端口修改方法
    谷歌启用抓取JavaScript,应对方案!
  • 原文地址:https://www.cnblogs.com/wangyiming/p/14939200.html
Copyright © 2020-2023  润新知