【Day45 LeetCode】图论题目 Ⅲ

打印 上一主题 下一主题

主题 816|帖子 816|积分 2448

一、图论题目 Ⅲ

1、淹没孤岛

这题只能从边界开始扩散,将靠近边界的陆地标志,表示不是孤岛,最后将孤岛淹没,将不是孤岛标志回陆地。
  1. # include<iostream>
  2. # include<vector>
  3. using namespace std;
  4. void dfs(vector<vector<int>> &graph, int i, int j){
  5.     if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[i][j]!=1)
  6.         return;
  7.     graph[i][j] = 2;
  8.     dfs(graph, i+1, j);
  9.     dfs(graph, i-1, j);
  10.     dfs(graph, i, j+1);
  11.     dfs(graph, i, j-1);
  12. }
  13. int main(){
  14.     int n, m;
  15.     cin >> n >> m;
  16.     vector<vector<int>> graph(n, vector<int>(m));
  17.     for(int i=0; i<n; ++i)
  18.         for(int j=0; j<m; ++j)
  19.             cin >> graph[i][j];
  20.    
  21.     // 步骤一:
  22.     // 从左侧边,和右侧边 向中间遍历
  23.     for (int i = 0; i < n; i++) {
  24.         if (graph[i][0] == 1) dfs(graph, i, 0);
  25.         if (graph[i][m - 1] == 1) dfs(graph, i, m - 1);
  26.     }
  27.     // 从上边和下边 向中间遍历
  28.     for (int j = 0; j < m; j++) {
  29.         if (graph[0][j] == 1) dfs(graph, 0, j);
  30.         if (graph[n - 1][j] == 1) dfs(graph, n - 1, j);
  31.     }
  32.     for (int i = 0; i < n; i++) {
  33.         for (int j = 0; j < m; j++) {
  34.             if (graph[i][j] == 1) graph[i][j] = 0;
  35.             if (graph[i][j] == 2) graph[i][j] = 1;
  36.         }
  37.     }
  38.     for (int i = 0; i < n; i++) {
  39.         for (int j = 0; j < m; j++) {
  40.             cout << graph[i][j] << " ";
  41.         }
  42.         cout << endl;
  43.     }
  44.     return 0;
  45. }
复制代码
2、水流题目

如果想着从当前点向两个边界移动的话,时间复杂度过高,因为需要遍历每个点,每个点又需要扩散到两个边界。如果我们逆向思维,想着从边界出发去找可达的点,这一下就豁然开朗了。
  1. # include<iostream>
  2. # include<vector>
  3. using namespace std;
  4. vector<vector<int>> dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
  5. void dfs(vector<vector<int>> &graph, vector<vector<bool>> &vis,int ii, int jj){
  6.     if(vis[ii][jj])
  7.         return;
  8.     vis[ii][jj] = true;
  9.     for(auto xy : dirs){
  10.         int i = ii + xy[0], j = jj + xy[1];
  11.         if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[ii][jj] > graph[i][j] || vis[i][j])
  12.             continue;
  13.         dfs(graph, vis, i, j);
  14.     }
  15. }
  16. int main(){
  17.     int n, m;
  18.     cin >> n >> m;
  19.     vector<vector<int>> graph(n, vector<int>(m));
  20.     for(int i=0; i<n; ++i)
  21.         for(int j=0; j<m; ++j)
  22.             cin >> graph[i][j];
  23.    
  24.     vector<vector<bool>> vis1(n, vector<bool>(m, false));
  25.     vector<vector<bool>> vis2(n, vector<bool>(m, false));
  26.    
  27.     for(int i=0; i<n; ++i){
  28.         dfs(graph, vis1, i, 0);
  29.         dfs(graph, vis2, i, m-1);
  30.     }
  31.     for(int i=0; i<m; ++i){
  32.         dfs(graph, vis1, 0, i);
  33.         dfs(graph, vis2, n-1, i);
  34.     }
  35.     for(int i=0; i<n; ++i){
  36.         for(int j=0; j<m; ++j){
  37.             if(vis1[i][j] && vis2[i][j])
  38.                 cout << i << " " << j << endl;
  39.         }
  40.     }
  41.     return 0;
  42. }
复制代码
3、建造最大岛屿

写了个很不优雅的代码,思路是 DFS遍历陆地,给每个岛屿一一对应的编号,并用哈希表记载编号与岛屿面积的对应关系。然后,第二次遍历图,碰到水域,遍历水域的四个方向上的编号,举行面积聚加,一个细节是需要用set举行去重,可能四个反向上存在编号雷同的区域。
  1. # include<iostream>
  2. # include<vector>
  3. # include<unordered_map>
  4. # include<unordered_set>
  5. using namespace std;
  6. int dfs(vector<vector<int>> &graph, int i, int j, int num){
  7.     if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[i][j]!=1)
  8.         return 0;
  9.     graph[i][j] = num;
  10.     return 1 + dfs(graph, i+1, j, num)+ dfs(graph, i-1, j, num)+ dfs(graph, i, j+1, num)+ dfs(graph, i, j-1, num);
  11. }
  12. int main(){
  13.     int n, m;
  14.     cin >> n >> m;
  15.     vector<vector<int>> graph(n, vector<int>(m));
  16.     for(int i=0; i<n; ++i)
  17.         for(int j=0; j<m; ++j)
  18.             cin >> graph[i][j];
  19.     unordered_map<int, int> mp; // 映射几号陆地 与 其面积关系
  20.     mp[0] = 0;
  21.     int idx = 2; // 几号陆地
  22.     int ans = 0;
  23.     for(int i=0; i<n; ++i){
  24.         for(int j=0; j<m; ++j){
  25.             if(graph[i][j]==1){
  26.                 mp[idx] = dfs(graph, i, j, idx);
  27.                 ans = max(ans, mp[idx]);
  28.                 ++idx;
  29.             }
  30.         }
  31.     }
  32.     vector<vector<int>> dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
  33.     for(int i=0; i<n; ++i){
  34.         for(int j=0; j<m; ++j){
  35.             if(graph[i][j]==0){
  36.                 int tmp = 1;
  37.                 unordered_set<int> set;
  38.                 for(auto xy : dirs){
  39.                     int x = i + xy[0], y = j + xy[1];
  40.                     if(x>=0 && x<n && y>=0 && y<m && set.find(graph[x][y])==set.end()){
  41.                         set.insert(graph[x][y]);
  42.                         tmp += mp[graph[x][y]];
  43.                     }
  44.                 }
  45.                 ans = max(ans, tmp);
  46.             }
  47.         }
  48.     }
  49.     cout << ans << endl;
  50.    
  51.     return 0;
  52. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

梦见你的名字

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表