LintCode 137. 克隆图

克隆一张无向图,图中的每个节点包含一个 label 和一个列表 neighbors

数据中如何表示一个无向图?http://www.lintcode.com/help/graph/

你的程序需要返回一个经过深度拷贝的新图。这个新图和原图具有同样的结构,并且对新图的任何改动不会对原图造成任何影响。

样例

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

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

我们能看到如下的图:

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



思路:无向图深拷贝,按照深度优先的方法就能完成。最重要是在拷贝的时候做到对于旧点与新点的一一对应,以及深度优先搜索里面重复访问点的去除。

代码:
/**
 * 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 == nullptr) return nullptr;
        UndirectedGraphNode* res = new UndirectedGraphNode(node->label);
        node_map[node] = res;
        _clone(res, node);
        return res;
    }

    void _clone(UndirectedGraphNode* new_point , UndirectedGraphNode* old_point){
        if(visited.count(old_point)) return;  //检测当前点是否已经被克隆过
        visited.insert(old_point);
        for(auto p:old_point->neighbors){
            if(! node_map.count(p)) {  //检测当前点是否已经存在(存在映射)
                UndirectedGraphNode * new_p = new UndirectedGraphNode(p->label);
                new_point->neighbors.push_back(new_p);
                node_map[p] = new_p;
                _clone(new_p, p);
            }else{
                new_point->neighbors.push_back(node_map[p]);
                _clone(node_map[p],p);
            }
        }
    }

private:
    unordered_map<UndirectedGraphNode*,UndirectedGraphNode*> node_map;//一一对应的节点使用unordered_map
    unordered_set<UndirectedGraphNode*> visited;//对已经完成过clone的点的标记
};

 

posted @ 2018-07-31 14:21  J1ac  阅读(368)  评论(0编辑  收藏  举报