问题:
给定n个节点,和节点之间的连线关系,构成有向图。
- 红线 red_edges:[a,b]: a->b
- 蓝线 blue_edges:[a,b]: a->b
求从节点0,到各个节点(红蓝线交替)的最短距离。
若对于某个节点不存在这样的通路,那么该节点的结果为-1。
Example 1: Input: n = 3, red_edges = [[0,1],[1,2]], blue_edges = [] Output: [0,1,-1] Example 2: Input: n = 3, red_edges = [[0,1]], blue_edges = [[2,1]] Output: [0,1,-1] Example 3: Input: n = 3, red_edges = [[1,0]], blue_edges = [[2,1]] Output: [0,-1,-1] Example 4: Input: n = 3, red_edges = [[0,1]], blue_edges = [[1,2]] Output: [0,1,2] Example 5: Input: n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]] Output: [0,1,1] Constraints: 1 <= n <= 100 red_edges.length <= 400 blue_edges.length <= 400 red_edges[i].length == blue_edges[i].length == 2 0 <= red_edges[i][j], blue_edges[i][j] < n
解法:BFS
- 状态: queue中同时保存两者,visited中,防止重复也保存该两个信息。
- 节点 id
- 到达当前节点的连线颜色 color
- 选择:
- 到达当前节点连线颜色为 red:那么在蓝线集合中,找该节点的下一个节点。
- 到达当前节点连线颜色为 blue:那么在红线集合中,找该节点的下一个节点。
- 初始化:节点0:
- 若n>0,那么一定存在0节点,res[0]=0
- 若红线集合中,有从0出发的连线,那么queue.push({0, blue}) visited.insert({0, blue});
- 若蓝线集合中,有从0出发的连线,那么queue.push({0, red}) visited.insert({0, red});
因为BFS的遍历层次从0开始,递增,那么先找到的结果,即为最短。值为level。
♻️ 优化:count记录更新过节点后,剩余未更新的节点个数。
若count提前==0,那么所有节点都找到了最近的距离。可停止遍历queue。
代码参考:
1 class Solution { 2 public: 3 //state: id, color 4 // level 5 //opt: 6 // color == 0 -> blue:1 7 // color == 1 -> red :0 8 vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& red_edges, vector<vector<int>>& blue_edges) { 9 vector<int> res(n, -1); 10 vector<unordered_map<int, vector<int>>> edges(2);//0:red, 1:blue 11 //initialize edges 12 for(vector<int>& r:red_edges) { 13 edges[0][r[0]].push_back(r[1]); 14 //cout<<"edges[0].back:"<<r[0]<<" Start:"<<edges[0][r[0]].back()<<endl; 15 } 16 for(vector<int>& b:blue_edges) { 17 edges[1][b[0]].push_back(b[1]); 18 //cout<<"edges[1].back:"<<b[1]<<" Start:"<<edges[1][b[0]].back()<<endl; 19 } 20 queue<pair<int, int>> q;//id, color 21 unordered_set<int> visited; 22 if(!edges[1][0].empty()) { 23 q.push({0,0}); 24 visited.insert(0*100+0); 25 } 26 if(!edges[0][0].empty()) { 27 q.push({0,1}); 28 visited.insert(0*100+1); 29 } 30 if(n>0) res[0]=0; 31 int level = 0; 32 int count = n-1; 33 while(!q.empty() && count!=0) { 34 int sz = q.size(); 35 for(int i=0; i<sz; i++) { 36 auto [id, color] = q.front(); 37 q.pop(); 38 //cout<<"pop:[id,color] "<<id<<","<<color<<" count:"<<count<<endl; 39 if(res[id]==-1) { 40 res[id] = level; 41 count--; 42 } 43 color = (color==1)?0:1; 44 for(int edg:edges[color][id]) { 45 if(visited.insert(edg*100+color).second) { 46 q.push({edg, color}); 47 } 48 } 49 } 50 level++; 51 } 52 return res; 53 } 54 };