这道题可以用DFS和BFS分别完成。
要说DFS和BFS讲的透彻的,还是算法导论,下面给出算法导论上的伪代码,注意,其中任何一行code都是非常值得玩味的:
BFS伪代码
BFS(G, s)
1 for each vertex u ∈ V [G] - {s}
2 do color[u] ← WHITE
3 d[u] ← ∞
4 π[u] ← NIL
5 color[s] ← GRAY
6 d[s] ← 0
7 π[s] ← NIL
8 Q ← Ø
9 ENQUEUE(Q, s)
10 while Q ≠ Ø
11 do u ← DEQUEUE(Q)
12 for each v ∈ Adj[u]
13 do if color[v] = WHITE
14 then color[v] ← GRAY
15 d[v] ← d[u] + 1
16 π[v] ← u
17 ENQUEUE(Q, v)
18 color[u] ← BLACK
当图中有环的时候,可能出现重复访问的情况,这时用color着色,防止重复访问已经访问过的节点。其实关键是Gray和White,Black就是标记这个节点是不是完全被访问完成了。
注意,之前访问过的节点根本不能进入队列。
DFS伪代码
DFS(G)
1 for each vertex u ∈ V [G]
2 do color[u] ← WHITE
3 π[u] ← NIL
4 time ← 0
5 for each vertex u ∈ V [G]
6 do if color[u] = WHITE
7 then DFS-VISIT(u)
DFS-VISIT(u)
1 color[u] ← GRAY
2 time ← time +1
3 d[u] <-time
4 for each v ∈ Adj[u]
5 do if color[v] = WHITE
6 then π[v] ← u
7 DFS-VISIT(v)
8 color[u] <-BLACK
9 f [u] ▹ time ← time +1
注意,也用着色来避免重复访问,关键也是Gray和White。当一个节点之前被访问过的情况下,无法递归调用DFS-VISIT。
另外,我们平时在写DFS的时候,尽量脑子只思考两层,第一层for循环,第二层递归,否则很容易晕。
BFS代码:
unordered_map<UndirectedGraphNode*,UndirectedGraphNode *> mp;
unordered_map<UndirectedGraphNode*,bool> color;
UndirectedGraphNode * bfs(UndirectedGraphNode *node){
if(node==NULL)
return NULL;
UndirectedGraphNode * root=new UndirectedGraphNode(node->label);
mp[node]=root;
queue<UndirectedGraphNode *> Q;
Q.push(node);
color[node]=true;
while(!Q.empty()){
UndirectedGraphNode * front=Q.front();
Q.pop();
for(int i=0;i<front->neighbors.size();i++){
if(color[front->neighbors[i]]!=true){
Q.push(front->neighbors[i]);
color[front->neighbors[i]]=true;
UndirectedGraphNode * temp=new UndirectedGraphNode(front->neighbors[i]->label);
mp[front->neighbors[i]]=temp;
mp[front]->neighbors.push_back(temp);
}
else{
mp[front]->neighbors.push_back(mp[front->neighbors[i]]);
}
}
}
return root;
}
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
return bfs(node);
}
DFS代码:
unordered_map<UndirectedGraphNode*,UndirectedGraphNode *> mp;
unordered_map<UndirectedGraphNode*,bool> color;
UndirectedGraphNode * dfs(UndirectedGraphNode *node,UndirectedGraphNode *parent){
if(node==NULL)
return NULL;
UndirectedGraphNode * me=NULL;
color[node]=true;
if(mp[node]==0){
me=new UndirectedGraphNode(node->label);
mp[node]=me;
}
else{
me=mp[node];
}
if(parent!=NULL)
parent->neighbors.push_back(me);
for(int i=0;i<node->neighbors.size();i++){
if(color[node->neighbors[i]]==true)
me->neighbors.push_back(mp[node->neighbors[i]]);
if(color[node->neighbors[i]]!=true)
dfs(node->neighbors[i],me);
}
return me;
}
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
return dfs(node,NULL);
}