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可以抽象成一 ...
随机推荐
- Logger之Logger.getLogger(CLass)技巧代替system.out.print
---恢复内容开始--- 尊重原创:http://www.cnblogs.com/zxf330301/p/5876117.html 之前一直在使用System.out.println()来调试.但是用 ...
- java实现死锁的demo
死锁 只有当t1线程占用o1且正好也需要o2,t2此时占用o2且正好也需要o1的时候才会出现死锁,(类似于2个人拿着两个筷子吃饭,都是需要对方的一根筷子才能吃) 以下代码t1线程占用o1,并且获取到o ...
- @synchronized(self)
@synchronized 的作用是创建一个互斥锁,保证此时没有其它线程对self对象进行修改.这个是objective-c的一个锁定令牌,防止self对象在同一时间内被其 它线程访问,起到线程的保护 ...
- CCF系列之ISBN号码(201312-2)
试题名称: ISBN号码 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规 ...
- MyCat 启蒙:分布式系统的数据库架构演变
文章首发于[博客园-陈树义],点击跳转到原文<MyCat 启蒙:分布式系统的数据库架构演变> 单数据库架构 一个项目在初期的时候,为了尽可能快地验证市场,其对业务系统的最大要求是快速实现. ...
- postgres的initdb解析——从一次插件升级失败说起
我们公司基于postgres开发了一款数据库产品,不用说我们对OSS的源码做了改动,并且也集成和自己编写了一些插件.因此,当postgresql和相关插件升级时,我们也需要将升级反应到自己的产品中去, ...
- Java线程-异常处理
在Java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉.这一点是通过java.lang.Run ...
- linux_http协议
什么是http协议? 超文本传输协议 最流行www服务,是http协议的实现 ssh,nfs,rsync客户端(Client)和服务端(Server),C/S架构,局域网内部用,胖客户端 http协议 ...
- python_如何让字典保持有序?
案例: 某编程竞赛系统,对参赛选手编程解题进行计时,选手完成题目后,把该选手解题用时记录到字典中,以便赛后按选手名查询成绩(答题时间越短,成绩越优秀) {'lili':(1,43),'yuyu':(2 ...
- JavaScript数组的22种方法
原文:http://www.cnblogs.com/xiaohuochai/p/5682621.html javascript中数组的22种方法 前面的话 数组总共有22种方法,本文将其分为对象继 ...