携程8.30笔试第三题【DFS】
题目:树的每个节点被染为rgb三色,求删掉一条边,满足分成两个连通块都恰好包含三种颜色的边的数量。
思路:统计子树中含有的rgb的数量,判断是否包含三种颜色,然后再用总的rgb数减去子树中的rgb数量,判断是否包含三种颜色。
public class Xiecheng830Q3 {
static int n, r, g, b;
static char[] colors;
static List<List<Integer>> nxs = new ArrayList<>();
static int res = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
sc.nextLine();
colors = sc.nextLine().toCharArray();
// 统计rgb的数量
for(char c : colors) {
if(c == 'r') r++;
else if(c == 'g') g++;
else b++;
}
// 初始化并构造无向图
for(int i = 0; i < n; i++) nxs.add(new LinkedList<>());
for(int i = 0; i < n - 1; i++) {
int a = sc.nextInt() - 1; //题目中给的下标是1开始
int b = sc.nextInt() - 1;
nxs.get(a).add(b);
nxs.get(b).add(a);
}
// 起点随便选,-1表示不存在的节点
dfs(1, -1);
System.out.println(res);
}
static int[] dfs(int node, int pre) {
int[] color = new int[3];
if(colors[node] == 'r') color[0]++;
else if(colors[node] == 'g') color[1]++;
else color[2]++;
//如果是叶子节点,就直接返回
if(nxs.get(node).size() == 1 && nxs.get(node).get(0) == pre) return color;
// 遍历相邻节点,把子树返回来的数量加到color里
for(int nx : nxs.get(node)) {
// nx != pre的条件是防止无向图往回走
if(nx != pre) add(color, dfs(nx, node));
}
// 判断是否符合题目条件
if(color[0] > 0 && color[1] > 0 && color[2] > 0 && r - color[0] > 0 && g - color[1] > 0 && b - color[2] > 0) res++;
return color;
}
// 数组相加
static void add(int[] a, int[] b) {
for(int i = 0; i < 3; i++) a[i] += b[i];
}
} 样例: 7
rgbrgbg
1 2
2 3
3 4
4 5
5 6
6 7
1 
