第38天--算法(最大食物链计数---笔试遇到无数次的算法题---Java题解)
题目描述
给你一个食物网,你要求出这个食物网中最大食物链的数量。
(这里的“最大食物链”,指的是生物学意义上的食物链,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。)
Delia 非常急,所以你只有 1 秒的时间。
由于这个结果可能过大,你只需要输出总数模上 80112002 的结果。
输入格式
第一行,两个正整数 n、m,表示生物种类 n 和吃与被吃的关系数 m。
接下来 m 行,每行两个正整数,表示被吃的生物A和吃A的生物B。
输出格式
一行一个整数,为最大食物链数量模上 80112002 的结果。
我的题解:深度优先遍历+记忆化搜索(不用记忆化搜索有部分测试用例会超时)
import java.util.*;
public class Main {
static int mod = 80112002;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int y = sc.nextInt();
int pre[][] = new int[y][2];
for(int i = 0;i < y;i ++) {
pre[i][0] = sc.nextInt();
pre[i][1] = sc.nextInt();
}
int sb[] = new int[x + 1];
int nb[] = new int[x + 1];
int ans = 0;
int map[] = new int[x + 1];
for(int i = 0;i < x + 1;i ++) {
map[i] = -999;
}
int lian[][] = new int[x + 1][x + 1];
// sb[xxx] == 0 -> 最垃圾的被吃的
// nb[xxx] == 0 -> 最牛逼的吃东西的
for(int i = 0;i < y;i ++) {
sb[pre[i][1]] ++;
nb[pre[i][0]] ++;
lian[pre[i][0]][pre[i][1]] = 1;
}
for(int i = 1;i <= x;i ++) {
if(nb[i] == 0) {
ans = (ans + dfs(lian,sb,nb,i,x,map)) % mod;
}
}
System.out.println(ans);
}
public static int dfs(int lian[][],int sb[],int nb[],int i,int x,int map[]) {
if(map[i] != -999) {
return map[i];
}
if(sb[i] == 0) {
return 1;
}
int ans = 0;
for(int j = 1;j <= x;j ++) {
if(lian[j][i] == 1) {
ans = (ans + dfs(lian,sb,nb,j,x,map)) % mod;
}
}
map[i] = ans;
return ans;
}
}