一看这道题自动机就好慌,但是多想想并不难。
S<=50,最长路根本不用考虑,直接考虑如何判断两个自动机是否一个是另一个的升级。
由于自动机的输出可以是无限的,因此不放压缩状态,用(x,y)表示在第一个自动机x点,第二个自动机y点可行,然后跑bfs,找是否存在(x,y)使x可以输出而y不行,若有则不符合。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 105
using namespace std;
int S,a[N],b[N],f[N][N],c[N][N][2],qx[N*N],qy[N*N],vis[N][N];
int Ans,dp[N],rd[N],d[N][N];
bool Get(int x,int y)
{
int l=0,r=1,tx,ty;
qx[1]=0;qy[1]=0;
memset(vis,0,sizeof vis);
vis[0][0]=1;
while(l<r)
{
l++;
if (f[x][qx[l]]&&(!f[y][qy[l]])) return 0;
for (int i=0;i<=1;i++)
{
tx=c[x][qx[l]][i];
ty=c[y][qy[l]][i];
if (!vis[tx][ty])
{
vis[tx][ty]=1;
r++;
qx[r]=tx;qy[r]=ty;
}
}
}
return 1;
}
void dfs(int x)
{
Ans=max(Ans,++dp[x]);rd[x]=-1;
for (int i=1;i<=S;i++)
if (d[x][i])
{
dp[i]=max(dp[i],dp[x]);
if (!(--rd[i])) dfs(i);
}
}
int main()
{
int x;
scanf("%d",&S);
for (int i=1;i<=S;i++)
{
scanf("%d%d",&a[i],&b[i]);
for (int j=1;j<=b[i];j++)
{
scanf("%d",&x);
f[i][x]=1;
}
for (int j=0;j<a[i];j++)
scanf("%d%d",&c[i][j][0],&c[i][j][1]);
}
for (int i=1;i<=S;i++)
for (int j=1;j<=S;j++)
if (i!=j)
{
if (Get(i,j)&&!d[j][i])
d[i][j]=1,rd[j]++;
}
for (int i=1;i<=S;i++)
if (!rd[i]) dfs(i);
printf("%d\n",Ans);
}