传送门

题意:

s个DFA,选出尽量多的自动机a0, a1, a2, . . . , at,使得a1包含a0、a2包 含a1,以此类推。s ≤ 50。

DFA的字符集为{0,1},有的节点是输出源,节点数n ≤ 50。


判断出包含关系后就是裸的最长路,求$SCC$后$DP$就好了

重点在判断包含:

$n$实在太小了,我们直接枚举所有的自动机,然后两个同时从起点开始$bfs$所有情况看看是否在某个状态一个有输出另一个没有

复杂度$O(n^4)$

注意:

$Candy?$这个沙茶$bfs$没有判断$(0,0)$状态是否一个输出一个不输出$WA$了好久,并且他还有一次求$SCC$没有枚举所有点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int s,n,m;
struct DFA{
int n,m,p[N][],out[N];
}a[N];
struct edge{
int v,ne;
}e[N*N<<],e2[N*N<<];
int h[N],cnt,h2[N],cnt2;
inline void ins(int u,int v){//printf("ins %d %d %d\n",cnt,u,v);
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
}
inline void ins2(int u,int v){//printf("ins2 %d %d\n",u,v);
edge *e=e2;int *h=h2,&cnt=cnt2;
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
}
struct node{
int x,y;
node(int a=,int b=):x(a),y(b){}
}q[N*N];
int head,tail;
bool vis[N][N];
void bfs(DFA &a,DFA &b,int i,int j){
int a_b=,b_a=;
memset(vis,,sizeof(vis));
head=tail=;
q[tail++]=node(,);vis[][]=;
while(head!=tail){
node u=q[head++];
int x=u.x , y=u.y;
if(a.out[x]&&!b.out[y]) b_a=;
if(!a.out[x]&&b.out[y]) a_b=;
if(a_b==&&b_a==) break;
for(int i=;i<=;i++){
int nx=a.p[x][i],ny=b.p[y][i];
if(!vis[nx][ny]){
vis[nx][ny]=;
q[tail++]=node(nx,ny);
}
}
}
if(a_b==) ins(i,j);
else if(b_a==) ins(j,i);
}
void buildGraph(){
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++) bfs(a[i],a[j],i,j);
} int dfn[N],dfc,low[N],scc,belong[N];
int st[N],top;
int val[N];
void dfs(int u){
dfn[u]=low[u]=++dfc;
st[++top]=u;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(!dfn[v]){
dfs(v);
low[u]=min(low[u],low[v]);
}else if(!belong[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
scc++;
while(true){
int x=st[top--];
belong[x]=scc;
val[scc]++;
if(x==u) break;
}
}
}
int f[N];
int dp(int u,int fa){
if(f[u]) return f[u];
for(int i=h2[u];i;i=e2[i].ne)
if(e2[i].v!=fa) f[u]=max(f[u],dp(e2[i].v,u));
return f[u]+=val[u];
}
int main(){
//freopen("in","r",stdin);
n=read();
for(int i=;i<=n;i++){
a[i].n=read();a[i].m=read();
for(int j=;j<=a[i].m;j++) a[i].out[read()]=;
for(int j=;j<a[i].n;j++) a[i].p[j][]=read(),a[i].p[j][]=read();
}
buildGraph();
for(int i=;i<=n;i++) if(!dfn[i]) dfs(i);
for(int u=;u<=n;u++)
for(int i=h[u];i;i=e[i].ne) if(belong[u]!=belong[e[i].v]) ins2(belong[u],belong[e[i].v]);
int ans=;
for(int i=;i<=scc;i++) ans=max(ans,dp(i,));
printf("%d\n",ans);
}

BZOJ 1194: [HNOI2006]潘多拉的盒子 [DP DFA]的更多相关文章

  1. 图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子

    1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 344  Solved: 181[Submit][Stat ...

  2. BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )

    O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...

  3. BZOJ 1194 [HNOI2006]潘多拉的盒子 (图论+拓扑排序+tarjan)

    题面:洛谷传送门 BZOJ传送门 标签里三个算法全都是提高组的,然而..这是一道神题 我们把这道题分为两个部分解决 1.找出所有咒语机两两之间的包含关系 2.求出咒语机的最长上升序列 我们假设咒语机$ ...

  4. 1194: [HNOI2006]潘多拉的盒子

    1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 464  Solved: 221[Submit][Stat ...

  5. 1194: [HNOI2006]潘多拉的盒子 - BZOJ

    Description  Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述.每一块的 ...

  6. BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)

    Description 传说中,有个神奇的潘多拉宝盒.如果谁能打开,便可以拥有幸福.财富.爱情.可是直到真的打开,才发现与之 相随的还有灾难.不幸.其实,在潘多拉制造这个宝盒的时候,设置了一些咒语来封 ...

  7. 【bzoj1194】 HNOI2006—潘多拉的盒子

    http://www.lydsy.com/JudgeOnline/problem.php?id=1194 (题目链接) 题意 给出S个自动机,如果一个自动机u的所有状态是另一个自动机v的状态的子集,那 ...

  8. 【强连通分量】Bzoj1194 HNOI2006 潘多拉的盒子

    Description Sulotion 首先要对每对咒语机建图,判断机器a是否能生成所有机器b生成的 如果跑一个相同的串,最后结束的点b可输出a不可输出,判断就为否 大概就用这种思路,f[x][y] ...

  9. HNOI2006 潘多拉的盒子

    题目描述 题解: 题目的描述比较长,理解起来也有一定难度.仔细读题后我们发现整个任务可以分成两个部分:找出咒语机之间所有的升级关系.求最长升级序列. 1. 求升级关系: 容易看出,咒语机i可以抽象成一 ...

随机推荐

  1. nodeJs文件系统(fs)与流(stream)

    一.简介 本文将介绍node.js文件系统(fs)和流(stream)的一些API已经参数使用情况. 二.目录 文件系统将介绍以下方法: 1.fs.readFile 2.fs.writeFile 3. ...

  2. 初识Spider_Man(爬爬虫)

    一:引子

  3. Spark算子--mapPartitions和mapPartitionsWithIndex

    mapPartitions--Transformation类算子 代码示例 result   mapPartitionsWithIndex--Transformation类算子 代码示例 result ...

  4. mysql中使用show table status 查看表信息

    学习标签: mysql 本文导读:在使用mysql数据库时,经常需要对mysql进行维护,查询每个库.每个表的具体使用情况,Mysql数据库可以通过执行SHOW TABLE STATUS命令来获取每个 ...

  5. 基于VUE选择上传图片并在页面显示(图片可删除)

    demo例子: 依赖文件 : http://files.cnblogs.com/files/zhengweijie/jquery.form.rar HTML文本内容: <template> ...

  6. Html Mailto标签详细使用方法

    http://www.360doc.com/content/09/0805/14/16915_4684377.shtml Html Mailto标签详细使用方法 Html中mailto标签是一个非常实 ...

  7. 从(0,0)到(m,n),每次走一步,只能向上或者向右走,有多少种路径走到(m,n)

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  8. mysql explain用法和结果的含义

    转自:http://blog.chinaunix.net/uid-540802-id-3419311.html explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择 ...

  9. CentOs下安装PHP扩展curl

    服务器运行一段时间后,可能突然会需求添加某个扩展,如curl.pdo.xmlrpc等,这就需要在不重新编译Linux PHP的情况下独立添加扩展. 1.安装crul wget http://curl. ...

  10. JavaScript ECMAScript版本介绍

    1. 介绍 1.1 什么是ECMAScript ECMAScript,简称ES,是由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers ...