行列累乗で挑んだけど、どうにも通らない。
行列やシミュレーションのようなアプローチだと mod が悪さをするらしく、複数の mod で試す必要があるらしい。
素直にグラフにしてやった。
path[ 0 ][ i ] == true
path[ i ][ i ] == true
out_degree[ i ] > 1
を満たす頂点が存在したら無限に増える。
const lli mod = 1000000007;
class MonsterFarm {
public:
int numMonsters(vector <string> T)
{
const int size = T.size();
bool reach[size][size];
fill(&reach[0][0], &reach[size - 1][size], 0);
lli g[size][size];
fill(&g[0][0], &g[size - 1][size], 0);
int deg[size];
fill(deg, deg + size, 0);
for (int i = 0; i < (int)T.size(); ++i) {
istringstream iss(T[i]);
for (string s; iss >> s; ) {
int j = atoi(s.c_str()) - 1;
++deg[i];
++g[i][j];
reach[i][j] = true;
}
}
for (int k = 0; k < (int)size; ++k) {
for (int i = 0; i < (int)size; ++i) {
for (int j = 0; j < (int)size; ++j) {
reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j]);
}
}
}
for (int i = 0; i < (int)size; ++i) {
if (reach[0][i] && reach[i][i] && 1 < deg[i]) {
return -1;
}
}
lli dp[2][size];
fill(&dp[0][0], &dp[2 - 1][size], 0);
dp[0][0] = 1;
for (int i = 0; i < (int)size; ++i) {
int curr = i % 2;
int next = (i + 1) % 2;
for (int j = 0; j < (int)size; ++j) {
dp[next][j] = 0;
}
for (int j = 0; j < (int)size; ++j) {
for (int k = 0; k < (int)size; ++k) {
dp[next][k] += dp[curr][j] * g[j][k];
dp[next][k] %= mod;
}
}
}
lli sum = 0;
for (int i = 0; i < (int)size; ++i) {
sum += dp[0][i];
sum %= mod;
}
return sum;
}
};