第38天--演算法(最大食物鏈計數---筆試遇到無數次的演算法題---Java題解)
阿新 • • 發佈:2022-03-09
題目描述
給你一個食物網,你要求出這個食物網中最大食物鏈的數量。
(這裡的“最大食物鏈”,指的是生物學意義上的食物鏈,即最左端是不會捕食其他生物的生產者,最右端是不會被其他生物捕食的消費者。)
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;
}
}