无向图 相邻节点染色

122 阅读1分钟

题目

image.png

  • 因为叶子节点不用管颜色,而其他节点都需要与它相邻节点一起凑齐三种颜色,所以选顶点的时候选至少有两个子节点的点
  • 对于顶点以其中一个子节点进行深度优先的情况,如果按每层一种颜色来染色,比如 1、2、3、1、2、3...或者1、3、2、1、3、2等等,只要3个颜色按顺序选,那么除了顶点的点就一定满足条件
  • 而要让顶点满足条件,如果其中一个点选了1、2、3的路线,那么另一个点只能1、3、2的路线,让顶点和子节点能凑齐1、2、3三种颜色
function process(edges, n) {
  const rule1 = [1, 2, 3];
  const rule2 = [1, 3, 2];

  const graph = new Map();
  for (let i = 0; i < n; i++) {
    graph.set(i, []);
  }
  // 构造无向图
  for (let i = 0; i < edges.length; i++) {
    graph.get(edges[0]).set(edges[1]);
    graph.get(edges[1]).set(edges[0]);
  }

  // 查找子节点数量大于2的节点,以该节点为头节点
  let head = -1;
  for (let i = 0; i < n; i++) {
    if (graph.get(i).length >= 2) {
      head = i;
      break;
    }
  }
  const colors = Array(n).fill(0);
  // 只存在一个子节点或者只有一个节点的情况 0<->0
  if (head === -1) {
    return Array(n).fill(1);
  } else {
    colors[head] = 1;
    // 其中一个节点方向走 1、2、3
    dfs(graph, graph.get(head)[0], 1, rules1, colors);
    // 剩余节点方向走 1、3、2 就能满足
    for (let i = 1; i < graph.get(head).length; i++) {
      dfs(graph, graph.get(head)[i], 1, rules2, colors);
    }
  }
  // level 表示当前节点的层级
  function dfs(graph, head, level, rules, colors) {
    colors[head] = rules[level % 3];
    for (let i = 0; i < graph.get(head).length; i++) {
      const child = graph.get(head)[i];
      // 因为是无向图遍历 0表示未被染色
      if (colors[child] === 0) {
        dfs(graph, child, level + 1, rule, colors);
      }
    }
  }

  return colors;
}