LeetCode 1129. 颜色交替的最短路径 思路易懂的bfs解法

26 阅读2分钟

题目如下: image.png

写法一: 因为边的颜色有两条,所以到达节点i的状态有dist[i][red]和dist[i][blue],同理可知visited的状态也有两种

public:
    vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& redEdges, vector<vector<int>>& blueEdges) {
        vector<vector<pair<int, int>>> grid(n + 5);
        for(auto edge : redEdges){
            int v = edge[0], u = edge[1];
            grid[v].emplace_back(u, 0);  //0表示红色边
            cout << v << " " << u <<endl;
        }
        for(auto edge : blueEdges){
            int v = edge[0], u = edge[1];
            grid[v].emplace_back(u, 1);  //1表示蓝色边
            cout << v << " " << u <<endl;
        }

        vector<int> ans(n, -1);
        ans[0] = 0;  //ans[0]恒为0
        queue<pair<int, int>> q;  //pair.second为边的颜色
        vector<vector<int>> visited(n + 5, vector<int>(2, -1));
        q.push({0, 0}); 
        q.push({0, 1});
        visited[0][0] = 1;
        visited[0][1] = 1;
        vector<vector<int>> dist(n + 5, vector<int>(2, 0));
        while(!q.empty()){
            int a = q.size();

            while(a--){
                pair<int, int> p = q.front();
                int v = p.first, color = p.second;
                q.pop();
                cout << "v : " << v << endl;
                for(auto edge : grid[v]){
                    
                    int next_v = edge.first, next_color = edge.second;
                    cout << "next_v : " << next_v << endl;
                    if(next_color == color) continue;  //边的颜色相同舍弃
                    if(visited[next_v][next_color] != -1) continue;  //该节点已经访问过了
                    
                    q.push({next_v, next_color});
                    cout << next_v << endl;
                    dist[next_v][next_color] = dist[v][color] + 1;
                    if(ans[next_v] == -1) ans[next_v] = dist[next_v][next_color];
                    else ans[next_v] = min(ans[next_v], dist[next_v][next_color]); 
                    visited[next_v][next_color] = 1;
                }
            }    
        }
        return ans;
    }
};

写法二: 将起始的入队状态压缩成只有-1一种,记录bfs的层数来计算距离,这样就可以简化dist的状态,不用开二维数组,其实甚至可以不用dist来记录了。

public:
    vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& redEdges, vector<vector<int>>& blueEdges) {
        vector<vector<pair<int, int>>> grid(n + 5);
        for(auto edge : redEdges){
            int v = edge[0], u = edge[1];
            grid[v].emplace_back(u, 0);  //0表示红色边
            //cout << v << " " << u <<endl;
        }
        for(auto edge : blueEdges){
            int v = edge[0], u = edge[1];
            grid[v].emplace_back(u, 1);  //1表示蓝色边
            //cout << v << " " << u <<endl;
        }

        vector<int> ans(n, -1);
        ans[0] = 0;  //ans[0]恒为0
        queue<pair<int, int>> q;  //pair.second为边的颜色
        vector<vector<int>> visited(n + 5, vector<int>(2, -1));
        q.push({0, -1});  
        
        visited[0][0] = 1;
        visited[0][1] = 1;
        //vector<vector<int>> dist(n + 5, vector<int>(2, 0));
        vector<int> dist(n + 5, 0);
        int step = 0;
        while(!q.empty()){
            int a = q.size();
            step++;
            while(a--){
                pair<int, int> p = q.front();
                int v = p.first, color = p.second;
                q.pop();
                //cout << "v : " << v << endl;
                for(auto edge : grid[v]){
                    
                    int next_v = edge.first, next_color = edge.second;
                    //cout << "next_v : " << next_v << endl;
                    if(next_color == color) continue;  //边的颜色相同舍弃
                    if(visited[next_v][next_color] != -1) continue;  //该节点已经访问过了
                    
                    q.push({next_v, next_color});
                    //cout << next_v << endl;
                    if(ans[next_v] == -1) ans[next_v] = step;
                    else ans[next_v] = min(ans[next_v], step); 
                    visited[next_v][next_color] = 1;
                }
            }    
        }
        return ans;
    }
};