20240227统计树中的合法路径数目
class Solution {
private static final int N = 100001;
private static boolean[] isPrime = new boolean[N];
static {
Arrays.fill(isPrime, true);
isPrime[1] = false;
for (int i = 2; i * i < N; ++i) {
if (isPrime[i]) {
for (int j = i * i; j < N; j += i) {
isPrime[j] = false;
}
}
}
}
public long countPaths(int n, int[][] edges) {
// 记录点连通的所有点
List<Integer>[] G = new ArrayList[n + 1];
// 初始化数组
for (int i = 0; i <= n; ++i) {
G[i] = new ArrayList<>();
}
// 填充连通点的信息
for (int[] edge : edges) {
int i = edge[0], j = edge[1];
G[i].add(j);
G[j].add(i);
}
// 访问过的记录
List<Integer> seen = new ArrayList<>();
// 结果答案
long res = 0;
long[] count = new long[n + 1];
for (int i = 1; i <= n; ++i) {
if (!isPrime[i]) {
continue;
}
long cur = 0;
for (int j : G[i]) {
if (isPrime[j]) {
continue;
}
if (count[j] == 0) {
seen.clear();
dfs(G, seen, j, 0);
long cnt = seen.size();
for (int k : seen) {
count[k] = cnt;
}
}
res += count[j] * cur;
cur += count[j];
}
res += cur;
}
return res;
}
private void dfs(List<Integer>[] G, List<Integer> seen, int i, int pre) {
seen.add(i);
for (int j : G[i]) {
// 树和图的区别就是树没有环,而图可能存在环,所以这里只需要判断当前节点和上一个节点不同即可
if (j != pre && !isPrime[j]) {
dfs(G, seen, j, i);
}
}
}
}
这里采用的是官方题解的答案,并配上自己的理解,如有错误,立马改正
质数的判断题解里采用的是埃氏筛,下面附上跳转链接
题目跳转链接
计数质数
解题步骤及说明
1.通过list数组,记录每个节点直接相连的节点信息
2.然后便利edge信息,初始化节点信息G
3.创建一个seen数组,用来记录节点遍历过程中合理的子节点。
4.遍历节点,如果当前节点是质数,则继续遍历连通节点,否则跳过
5.遍历子节点,用count数组中的缓存来判断一个数是否处理过,如果处理过则跳过,直接使用缓存
6.清空seen缓存,调用dfs方法使用深度优先搜索计算当前节点的所有子节点中不存在质数的路径,因为循环的第一个必要条件就是当前数为质数,所以当前dfs搜索只需要查询不存在质数的路径条数有多少
7.遍历当前节点的子节点,如果子节点不等于前置节点并且不是质数,则继续向下搜索,否则搜索结束,返回结果(注: 这里说明一下,这里为什么只判断子节点和前置节点不同即可,会不会存在子节点的子节点和前置节点相同,这里需要说明一下,树和图的区别,树是没有环的,而图可能存在环,所以只需判断前置节点和当前节点不同即可过滤掉重复数据)
8.dfs结束,则seen中获取到了当前节点的所有不存非质数的子节点
9.继续下一个节点的搜索,这里我们注意到cur这个字段记录的是当前一共有多少个非质数的子节点,然后结果res加上cur*count,然后对cur进行累加


浙公网安备 33010602011771号