# LeetCode | Clone Graph（克隆图）

Clone an undirected graph. Each node in the graph contains a `label` and a list of its `neighbors`.

OJ’s undirected graph serialization:

Nodes are labeled uniquely.

We use
`#` as a separator for each node, and
`,` as a separator for node label and each neighbor of the node.

As an example, consider the serialized graph `{0,1,2#1,2#2,2}`.

The graph has a total of three nodes, and therefore contains three parts as separated by `#`.

1. First node is labeled as `0`. Connect node `0` to both nodes `1` and `2`.
2. Second node is labeled as `1`. Connect node `1` to node `2`.
3. Third node is labeled as `2`. Connect node `2` to node `2` (itself), thus forming a self-cycle.

Visually, the graph looks like the following:

```       1
/ \
/   \
0 --- 2
/ \
\_/```

``````//广度优先
class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if(node == NULL)
return node;
UndirectedGraphNode *clone = NULL;
queue<UndirectedGraphNode *> originalqu;
queue<UndirectedGraphNode *> clonequ;
map<int,UndirectedGraphNode*> graphmap;
map<int,UndirectedGraphNode*> orimap;
originalqu.push(node);
clone = new UndirectedGraphNode(node->label);
clonequ.push(clone);
graphmap[node->label] = clone;
orimap[node->label] = node;
while(!originalqu.empty()){
UndirectedGraphNode *originalnode = originalqu.front();
originalqu.pop();
UndirectedGraphNode *clonenode = clonequ.front();
clonequ.pop();

for(int i = 0;i < originalnode->neighbors.size();i++){
UndirectedGraphNode *tmp = (originalnode->neighbors)[i];

map<int,UndirectedGraphNode*>::iterator it = graphmap.find(tmp->label);
if(it != graphmap.end()){
clonenode->neighbors.push_back(it->second);
clonequ.push(it->second);
}else{
UndirectedGraphNode *p = new UndirectedGraphNode(tmp->label);
(clonenode->neighbors).push_back(p);
graphmap[tmp->label] = p;
clonequ.push(p);
}
if(orimap.find(tmp->label) != orimap.end())
continue;
orimap[tmp->label] = tmp;
originalqu.push(tmp);
}
}
return clone;
}
};
``````

``````class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if(node==NULL)
{
return NULL;
}
map<int, UndirectedGraphNode*> nodes;
queue<UndirectedGraphNode*> q;

q.push(node);

while(!q.empty())
{
UndirectedGraphNode* tmp = q.front();
q.pop();
if(nodes.find(tmp->label)==nodes.end()) //避免重复
{
UndirectedGraphNode* new_node = new UndirectedGraphNode(tmp->label);
nodes.insert(pair<int, UndirectedGraphNode*>(new_node->label, new_node));
for(int i=0;i<tmp->neighbors.size();i++)
{
q.push(tmp->neighbors[i]);  //先将子节点全部放入队列中，无论有没有重复，然后出栈创建元素时再判断
}
}
}

q.push(node);
while(!q.empty())
{
UndirectedGraphNode* tmp = q.front();
q.pop();
UndirectedGraphNode* existingnode = nodes[tmp->label];
if(existingnode->neighbors.empty()&&!tmp->neighbors.empty())
{
for(int i=0;i<tmp->neighbors.size();i++)
{
existingnode->neighbors.push_back(nodes[tmp->neighbors[i]->label]);
q.push(tmp->neighbors[i]);
}
}
}

return nodes[node->label];
}
};
``````

1. 这题明说, label 独一无二, 那么就可以使用 hash map 存储元素

2. BFS 搜索, 边搜边向 hash map 添加元素

3. 在设置标记位上 TLE 了 N 次, 一个元素一旦被假如到 hash map, 就说明该元素已经被访问到了并已被假如到 queue 中, 同时环的问题也被克服了. 我在做的时候, 把环的问题拉出来单独处理, 但标记忘记了

4. unordered_map<node*, node*> 这种设置不是第一次见到了, 比设置成 unordered_map<int, node*> 要方便一些

5. map.count 比 map.find 要精练一些

6. 加入 map 时, 可以直接 map[] = xxx, 不用判断是否已有

``````class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> record;
if(node == NULL)
return node;

deque<UndirectedGraphNode*> queue;
queue.push_back(node);

while(!queue.empty()) {
UndirectedGraphNode *nextNode = queue.front();
queue.pop_front();

if(!record.count(nextNode)) {   //只有在第一个元素时创建该结点，后面的已经在for循环中创建好
UndirectedGraphNode *newNode = new UndirectedGraphNode(nextNode->label);
record[nextNode] = newNode;
}
for(int i = nextNode->neighbors.size()-1; i >= 0 ; i --) {
UndirectedGraphNode *childNode = nextNode->neighbors[i];
if(!record.count(childNode)) {  //如果没有在map中，就创建结点并放入队列中
UndirectedGraphNode *newNode = new UndirectedGraphNode(childNode->label);
record[childNode] = newNode;
queue.push_back(childNode);
}   //通过map的键值找到克隆的指针，直接将要链接的子节点的克隆填入，方法太好了
record[nextNode]->neighbors.push_back(record[childNode]);
}
}
return record[node];
}
};
``````