lintcode-137-克隆图

137-克隆图

克隆一张无向图,图中的每个节点包含一个 label 和一个列表 neighbors。
数据中如何表示一个无向图?http://www.lintcode.com/help/graph/
你的程序需要返回一个经过深度拷贝的新图。这个新图和原图具有同样的结构,并且对新图的任何改动不会对原图造成任何影响。

样例

比如,序列化图 {0,1,2#1,2#2,2} 共有三个节点, 因此包含两个个分隔符#。

  • 第一个节点label为0,存在边从节点0链接到节点1和节点2
  • 第二个节点label为1,存在边从节点1连接到节点2
  • 第三个节点label为2,存在边从节点2连接到节点2(本身),从而形成自环。

我们能看到如下的图:
lintcode-137-克隆图

标签

宽度优先搜索 脸书

思路

使用宽度优先搜索遍历原图的同时创建新图。使用 oldToNew 保存原图与新图同个节点的对应关系,用 isVisited 保存原图的某点是否被遍历。具体过程如下:

  • 对原图的第一个节点 node,新建一个节点 newNode 与 node 对应,即oldToNew[node] = newNode,并标记 node 已遍历,即 isVisited[node] = true,将 node 入队
  • 队列不为空时:
    队首元素 node 出队,遍历与 node 相连的节点,即 node->neighbors[i],
    若 node->neighbors[i] 未被遍历过,建立新节点与其对应,标记此结点以便利,将新节点连入新图
    若 node->neighbors[i] 已被遍历,将此结点对应的新节点连入新图

code

/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    /**
     * @param node: A undirected graph node
     * @return: A undirected graph node
     */
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        // write your code here
        if(node == NULL) {
            return node;
        }

        queue<UndirectedGraphNode*> willVisit;
        map<UndirectedGraphNode*, bool> isVisited;
        map<UndirectedGraphNode*, UndirectedGraphNode*> oldToNew;

        UndirectedGraphNode * newNode = new UndirectedGraphNode(node->label);
        isVisited[node] = true;
        oldToNew[node] = newNode;
        willVisit.push(node);

        while(!willVisit.empty()) {
            node = willVisit.front();
            willVisit.pop();
            for(int i=0; i<node->neighbors.size(); i++) {
                if(isVisited[node->neighbors[i]] == false) {
                    UndirectedGraphNode * temp = new UndirectedGraphNode(node->neighbors[i]->label);
                    isVisited[node->neighbors[i]] = true;
                    oldToNew[node->neighbors[i]] = temp;
                    oldToNew[node]->neighbors.push_back(temp);
                    willVisit.push(node->neighbors[i]);
                }
                else {
                    oldToNew[node]->neighbors.push_back(oldToNew[node->neighbors[i]]);
                }
            }
        }

        return newNode;
    }
};