这道题的题意也是醉了 看了半天
其实也挺水的嘛2333
搬来PO姐写的 题目大意:给定一些自动机,如果某个自动机A能产生的所有串都能在自动机B中产生,则称B是A的一个升级,求最长链
然后就不难想到两两连边接着tarjan缩点 用拓扑求个最长链就好了
怎么确定升级关系呢? N只有50啊。。
我们用一个二元组(x,y)表示走了某个串后A走到了节点x,B走到了节点y,那么如果x是输出节点而y不是,则不满足条件,否则继续广搜(x,y)的两个后继
由于这样的二元组(x,y)只有
O(n2)
个
总的时间复杂度就是
O(n4)
代码应该挺。。。简洁的吧
#include<bits/stdc++.h>
#define me(a,x) memset(a,x,sizeof a)
using namespace std;
const int N=52,M=N*N;
inline int read()
{
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x*f;
}
struct edge{int x,y,next;}a[M],e[M]; int len,first[N];
void ins(int x,int y){a[++len]=(edge){x,y,first[x]},first[x]=len;}
int dfn[N],low[N],id,st[N],tp,bl[N],num[N],cnt,f[N],r[N];
bool in[N],bo[N][N];
void dfs(int x){
dfn[x]=low[x]=++id,st[++tp]=x,in[x]=1;
for(int k=first[x];k;k=e[k].next){
int y=e[k].y;
if(!dfn[y])dfs(y),low[x]=min(low[x],low[y]);
else if(in[y])low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x]){
int i; cnt++;
do{
i=st[tp--],in[i]=0,bl[i]=cnt,num[cnt]++;
}while(i!=x);
}
}
struct node{
int n,m,p[N][2];bool op[N];
node(){me(op,0);}
}c[N];
struct g{int x,y;};
queue<g>q;
bool bfs(int u1,int u2){
while(!q.empty())q.pop();
q.push((g){0,0}); me(bo,0);
while(!q.empty()){
g u=q.front(); q.pop();
for(int k=0;k<2;k++){
g o=(g){c[u1].p[u.x][k],c[u2].p[u.y][k]};
if(bo[o.x][o.y])continue; bo[o.x][o.y]=1;
if(c[u2].op[o.y] && !c[u1].op[o.x])return 0;
q.push(o);
}
}
return 1;
}
queue<int>Q;
int main()
{
int n=read(),i,j;
for(i=1;i<=n;i++){
c[i].n=read(),c[i].m=read();
for(j=0;j<c[i].m;j++)c[i].op[read()]=1;
for(j=0;j<c[i].n;j++)c[i].p[j][0]=read(),c[i].p[j][1]=read();
}
for(i=1;i<=n;i++)for(j=1;j<=n;j++)
if(i!=j && bfs(i,j))e[++len]=(edge){i,j,first[i]},first[i]=len;
for(i=1;i<=n;i++)if(!dfn[i])dfs(i);
int l=len; len=0; me(first,0);
for(i=1;i<=l;i++)
if(bl[e[i].x]!=bl[e[i].y])
ins(bl[e[i].x],bl[e[i].y]),r[bl[e[i].y]]++;
for(i=1;i<=cnt;i++)
if(!r[i])Q.push(i),f[i]=num[i];
int ans=0;
while(!Q.empty()){
int x=Q.front(); Q.pop(); ans=max(f[x],ans);
for(int k=first[x];k;k=a[k].next){
int y=a[k].y; r[y]--;
f[y]=max(f[y],f[x]+num[y]);
if(!r[y])Q.push(y);
}
}
printf("%d\n",ans);
return 0;
}