传送门

题意:

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. vim与外部文件的粘帖复制

    vim与外部文件的粘帖复制 ubuntu默认vim是不支持从外部文件与vim之间的粘帖复制,vim有自己的剪切版,分别是”0-”9,”-,”8,”+,”:,”/,”%,”i,这些都是vim的寄存器,可 ...

  2. Linux 文件操作命令-Linux基础环境命令学习笔记

    1.文件目录操作 1)路径识别 a.绝对路径,以根目录开始 b.相对路径,以当前目录开始,不需从根目录开始写起 2)命令 man ls 查看ls命令帮助 cd /var/log 切换进入log目录(. ...

  3. JXLS 2.4.0系列教程(三)——嵌套循环是怎么做到的

    注:本文代码在第一篇文章基础上修改而成,请务必先阅读第一篇文章. http://www.cnblogs.com/foxlee1024/p/7616987.html 本文也不会过多的讲解模板中遍历表达式 ...

  4. [国嵌攻略][106][Linux内存管理子系统]

    内存管理子系统 1.虚拟地址与物理地址的映射 2.物理内存的分配 Linux虚拟地址空间分布 设备最后访问的一定是物理地址,但Linux系统中使用的都是虚拟地址.虚拟地址简单的来说就是程序中使用的地址 ...

  5. 将项目(代码)从GitHub上克隆(下载)到本地仓库

    要将项目从GitHub上克隆到本地,首先你得下载并安装好git for window. 下载地址:http://www.xp510.com/xiazai/Application/other/30988 ...

  6. 遍历Map集合:java.util.Map.Entry、KeySet两种方式

    遍历Map集合的两种方式: 1.用KeySet Map.keySet(),返回一个存放所有key的set集合,通过遍历集合,根据key值取出所有的value值. Map<String,Strin ...

  7. light oj 1152 Hiding Gold

    题目: You are given a 2D board where in some cells there are gold. You want to fill the board with 2 x ...

  8. c++---天梯赛---N个数求和

    ★题目: ★难点:要求只能以有理数和分数去输出结果. ★分析:可以对输入的数据进行通分处理,随后把结果按格式输出. ★代码: #include<iostream> #include< ...

  9. jdbc、Mybatis插入数据主键回显的实现方法

    插入数据的时候,往往需要获取主键值.但是有时候主键是自增长的那么,就不太适用手动添加主键值了,此时需要一种可以回显主键参数的方法, 下面以jdbc.mybatis的实现举例 此时使用的是jdbc的话或 ...

  10. Vuejs实例-00Vuejs2.0全家桶结合ELementUI制作后台管理系统

    Vuejs2.0全家桶结合ELementUI制作后台管理系统 0: 系统环境的介绍 1: Vuejs实例-01使用vue-cli脚手架搭建Vue.js项目 2: Vuejs实例-02Vue.js项目集 ...