BZOJ 1194: [HNOI2006]潘多拉的盒子 [DP DFA]
题意:
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]的更多相关文章
- 图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 344 Solved: 181[Submit][Stat ...
- BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )
O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...
- BZOJ 1194 [HNOI2006]潘多拉的盒子 (图论+拓扑排序+tarjan)
题面:洛谷传送门 BZOJ传送门 标签里三个算法全都是提高组的,然而..这是一道神题 我们把这道题分为两个部分解决 1.找出所有咒语机两两之间的包含关系 2.求出咒语机的最长上升序列 我们假设咒语机$ ...
- 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 464 Solved: 221[Submit][Stat ...
- 1194: [HNOI2006]潘多拉的盒子 - BZOJ
Description Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述.每一块的 ...
- BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)
Description 传说中,有个神奇的潘多拉宝盒.如果谁能打开,便可以拥有幸福.财富.爱情.可是直到真的打开,才发现与之 相随的还有灾难.不幸.其实,在潘多拉制造这个宝盒的时候,设置了一些咒语来封 ...
- 【bzoj1194】 HNOI2006—潘多拉的盒子
http://www.lydsy.com/JudgeOnline/problem.php?id=1194 (题目链接) 题意 给出S个自动机,如果一个自动机u的所有状态是另一个自动机v的状态的子集,那 ...
- 【强连通分量】Bzoj1194 HNOI2006 潘多拉的盒子
Description Sulotion 首先要对每对咒语机建图,判断机器a是否能生成所有机器b生成的 如果跑一个相同的串,最后结束的点b可输出a不可输出,判断就为否 大概就用这种思路,f[x][y] ...
- HNOI2006 潘多拉的盒子
题目描述 题解: 题目的描述比较长,理解起来也有一定难度.仔细读题后我们发现整个任务可以分成两个部分:找出咒语机之间所有的升级关系.求最长升级序列. 1. 求升级关系: 容易看出,咒语机i可以抽象成一 ...
随机推荐
- Oracle_单行函数
Oracle_单行函数 --dual是一张虚拟表,用于做测试 select sysdate from dual; select from dual; 字符函数initcap(),lower(), ...
- phpfpm配置 php中的坑
###### 记一些坑```//phpfpm配置pm.max_children = 最大并发数详细的答案:pm.max_children 表示 php-fpm 能启动的子进程的最大数量.因为 php- ...
- Cannot complete the install because one or more required items could not be found
弄了一天的subclipse也没装上,郁闷~~~~~~~~ 无论采用本地安装还是站点安装都不行,在安装的时候显示错误: Cannot complete the install because one ...
- UltraEdit激活方法
按照UltraEdit 并下载注册机后. 打开UltraEdit 弹出产品是使用 然后点击 输入注册码, 重点:断开网络 点击激活,弹出 离线激活选项. 用户名密码随意输入,打开注册机,把下面的 ...
- python基础5之装饰器
内容概要: 一.装饰器前期知识储备 1.python解释函数代码过程: python解释器从上往下顺序解释代码,碰到函数的定义代码块不会立即执行它,而是将其放在内存中,等到该函数被调用时,才执行其内部 ...
- IIS命令行管理工具使用
AppCmd.exe工具所在目录 C:\windows\sytstem32\inetsrv\目录下 一条命令批量添加应用程序 c:\Windows\System32\inetsrv>for /d ...
- 2017-06-26(groupadd groupmod groupdel)
groupadd groupadd 组名 (创建用户组) groupadd -g 组编号 组名 (创建组名 并且指定编号) groupmod groupmod -n 新组名 旧组名 ...
- python 程序退出方式
sys.exit() 执行该语句会直接退出程序,这也是经常使用的方法,也不需要考虑平台等因素的影响,一般是退出Python程序的首选方法. 该方法中包含一个参数status,默认为0,表示正常退出,也 ...
- hibernate解读之session--基于最新稳定版5.2.12
前言 hibernate是一个实现了JPA标准的,用于对象持久化的orm框架.博主近一年开发都在使用. 前段时间在工作中遇到了一个hibernate的问题,从数据库查找得到对象后,修改了其中部分字段值 ...
- common-logging--源码之SimpleLog
common-logging源码Log接口 在common-logging的源码中,将log核心类抽象成了一个Log接口. 这里贴出Log接口的源码: /* * Licensed to the Apa ...