【Day45 LeetCode】图论问题 Ⅲ

一、图论问题 Ⅲ

1、沉没孤岛

这题只能从边界开始扩散,将靠近边界的陆地标记,表示不是孤岛,最后将孤岛沉没,将不是孤岛标记回陆地。

# include
# include

using namespace std;

void dfs(vector> &graph, int i, int j){
    if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[i][j]!=1)
        return;
    graph[i][j] = 2;
    dfs(graph, i+1, j);
    dfs(graph, i-1, j);
    dfs(graph, i, j+1);
    dfs(graph, i, j-1);
}

int main(){
    int n, m;
    cin >> n >> m;
    vector> graph(n, vector(m));
    for(int i=0; i> graph[i][j];
    
    // 步骤一:
    // 从左侧边,和右侧边 向中间遍历
    for (int i = 0; i < n; i++) {
        if (graph[i][0] == 1) dfs(graph, i, 0);
        if (graph[i][m - 1] == 1) dfs(graph, i, m - 1);
    }

    // 从上边和下边 向中间遍历
    for (int j = 0; j < m; j++) {
        if (graph[0][j] == 1) dfs(graph, 0, j);
        if (graph[n - 1][j] == 1) dfs(graph, n - 1, j);
    }


    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (graph[i][j] == 1) graph[i][j] = 0;
            if (graph[i][j] == 2) graph[i][j] = 1;
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cout << graph[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

2、水流问题

如果想着从当前点向两个边界移动的话,时间复杂度过高,因为需要遍历每个点,每个点又需要扩散到两个边界。如果我们逆向思维,想着从边界出发去找可达的点,这一下就豁然开朗了。

# include
# include

using namespace std;

vector> dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
void dfs(vector> &graph, vector> &vis,int ii, int jj){
    if(vis[ii][jj])
        return;
    vis[ii][jj] = true;
    for(auto xy : dirs){
        int i = ii + xy[0], j = jj + xy[1];
        if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[ii][jj] > graph[i][j] || vis[i][j])
            continue;
        dfs(graph, vis, i, j);
    }
}


int main(){
    int n, m;
    cin >> n >> m;
    vector> graph(n, vector(m));
    for(int i=0; i> graph[i][j];
    
    vector> vis1(n, vector(m, false));
    vector> vis2(n, vector(m, false)); 
    
    for(int i=0; i

3、建造最大岛屿

写了个很不优雅的代码,思路是 DFS遍历陆地,给每个岛屿一一对应的编号,并用哈希表记录编号与岛屿面积的对应关系。然后,第二次遍历图,遇到水域,遍历水域的四个方向上的编号,进行面积累加,一个细节是需要用set进行去重,可能四个反向上存在编号相同的区域。

# include
# include
# include
# include
using namespace std;

int dfs(vector> &graph, int i, int j, int num){
    if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[i][j]!=1)
        return 0;
    graph[i][j] = num;
    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);
} 

int main(){
    int n, m;
    cin >> n >> m;
    vector> graph(n, vector(m));
    for(int i=0; i> graph[i][j];
    unordered_map mp; // 映射几号陆地 与 其面积关系
    mp[0] = 0;
    int idx = 2; // 几号陆地 
    int ans = 0;
    for(int i=0; i> dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    for(int i=0; i set;
                for(auto xy : dirs){
                    int x = i + xy[0], y = j + xy[1];
                    if(x>=0 && x=0 && y

你可能感兴趣的:(图论,leetcode,深度优先)