题面:洛谷传送门 BZOJ传送门

标签里三个算法全都是提高组的,然而..这是一道神题

我们把这道题分为两个部分解决

1.找出所有咒语机两两之间的包含关系

2.求出咒语机的最长上升序列

我们假设咒语机$a,b$满足$a\in b$

如果这个条件不成立,说明存在一个串$S$,$a$能输出,$b$不能输出

一个咒语机能产生的字符串可能是无限长的,直接枚举字符串肯定不行

考虑转化问题

我们构造另外一个图,图中每个点是一个二元组$(x,y)$

我们暴力枚举咒语机$a$中的一个元件$x$,$b$中的一个元件$y$

我们把$(x,y)$分别向$(p_{x,0},p_{y,0}),(p_{x,1},p_{y,1})$连边

如果从$(0,0)$开始,走到了一个节点$(x,y)$,且$x$是$S$的一个输出点,而$y$却不是

说明$a\in b$不成立

因为从$(0,0)$走到$(x,y)$这样一条路径,对于$a,b$来说,是它们都能表示出来的字符串

即$a$中从$0$号元件走到$x$,$b$中从$0$号元件走到$y$,它们走出来的路径表示的字符串相同

而$a$能把它输出,$b$却不能,那么一定不满足$a\in b$

我们解决了第一个部分

我们得到了咒语机(点的集合)之间的关系,现在我们要求出它的最长上升序列

拓扑排序裸题吧

然而可能会出现环,即某些咒语机能表示出来的字符串集合相同

用$tarjan$缩点重新建出拓扑图,拓扑排序跑最长路即可

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 2505
#define M1 55
using namespace std; struct Graph{
int p[M1][],out[M1],n,m;
void Read()
{
int i,x;
scanf("%d%d",&n,&m);
for(i=;i<=m;i++) scanf("%d",&x),out[x+]=;
for(i=;i<=n;i++) scanf("%d%d",&p[i][],&p[i][]),p[i][]++,p[i][]++;
}
}g[M1];
struct Edge{
int head[N1],nxt[N1<<],to[N1<<],cte;
void ae(int u,int v){ cte++; to[cte]=v; nxt[cte]=head[u]; head[u]=cte; }
}e,E,N; int nt[N1],que[N1],hd,tl,vis[N1],inc[M1];
void init()
{
memset(&e,,sizeof(e));
memset(nt,,sizeof(nt));
memset(vis,,sizeof(vis));
}
int solve(Graph &ss,Graph &tt)
{
int i,j,x,v,ans=-; init();
for(i=;i<=ss.n;i++)
for(j=;j<=tt.n;j++)
{
x=(i-)*tt.n+j;
v=(ss.p[i][]-)*tt.n+tt.p[j][]; e.ae(x,v);
v=(ss.p[i][]-)*tt.n+tt.p[j][]; e.ae(x,v);
if(ss.out[i]&&!tt.out[j]) nt[x]=;
if(!ss.out[i]&&tt.out[j]) nt[x]=-;
}
hd=,tl=; que[++tl]=; vis[]=;
while(hd<=tl)
{
x=que[hd++];
if(nt[x])
{
if(ans==-) ans=nt[x];
else if(ans!=nt[x]) return ;
}
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j];
if(!vis[v]) que[++tl]=v, vis[v]=;
}
}
return ans;
}
int low[M1],dfn[M1],use[M1],stk[M1],tim,tp;
int num[M1],nn,dad[M1],f[M1];
void tarjan(int x,int fa)
{
int j,v;
low[x]=dfn[x]=++tim;
stk[++tp]=x; use[x]=;
for(j=E.head[x];j;j=E.nxt[j])
{
v=E.to[j];
if(v==fa) continue;
if(!dfn[v]){
tarjan(v,x);
low[x]=min(low[x],low[v]);
}else if(use[v]){
low[x]=min(low[x],dfn[v]);
}
}
if(low[x]==dfn[x])
{
nn++;
while(stk[tp]!=x)
{
use[stk[tp]]=,dad[stk[tp]]=nn;
tp--,num[nn]++;
}
dad[x]=nn, use[x]=, tp--, num[nn]++;
}
} int S; int main()
{
scanf("%d",&S);
int i,j,k,s,sx,sy,x,v,ans=;
for(s=;s<=S;s++) g[s].Read();
for(sx=;sx<=S;sx++)
for(sy=sx+;sy<=S;sy++)
{
k=solve(g[sx],g[sy]);
if(!k) continue;
if(ans==-) E.ae(sx,sy), E.ae(sy,sx);
else if(k==-) E.ae(sx,sy);
else E.ae(sy,sx);
}
for(s=;s<=S;s++)
if(!dfn[s]) tarjan(s,-);
for(x=;x<=S;x++)
for(j=E.head[x];j;j=E.nxt[j])
{
v=E.to[j];
if(dad[x]!=dad[v])
N.ae(dad[x],dad[v]), inc[dad[v]]++;
}
hd=,tl=;
for(i=;i<=nn;i++) if(!inc[i]) que[++tl]=i;
memset(use,,sizeof(use));
while(hd<=tl)
{
x=que[hd++]; ans=max(ans,f[x]);
for(j=N.head[x];j;j=N.nxt[j])
{
v=N.to[j];
f[v]=max(f[v],f[x]+); inc[v]--;
if(!inc[v]) que[++tl]=v;
}
}
printf("%d\n",ans+);
}

BZOJ 1194 [HNOI2006]潘多拉的盒子 (图论+拓扑排序+tarjan)的更多相关文章

  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]潘多拉的盒子 [DP DFA]

    传送门 题意: s个DFA,选出尽量多的自动机a0, a1, a2, . . . , at,使得a1包含a0.a2包 含a1,以此类推.s ≤ 50. DFA的字符集为{0,1},有的节点是输出源,节 ...

  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. Java基础教程:tutorialspoint-spring mvc

    教程: 来自turorialspoint的Spring MVC 4.1.6教程(英文),官网:https://www.tutorialspoint.com/springmvc/index.htm 离线 ...

  2. Eclipse快捷操作

    Eclipse快捷操作 快捷操作,包含了一些鼠标的操作: 学习了:http://www.cnblogs.com/iamfy/archive/2012/07/11/2586869.html 自己体会了一 ...

  3. 面向基于英特尔&#174; 架构的 Android* 的 CoCos2D

    Cocos2D 是一款游戏引擎,可与从电脑到手机等多种设备配合使用. 该引擎支持丰富的特性,可帮助创建出色的 2D 游戏.它甚至包含具备全面功能的物理引擎. CoCos2D 的核心元素是基本动画元素( ...

  4. JAVA经常使用数据结构及原理分析

    前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源代码,balabala讲了一堆,如今总结一下. java.util包中三个重要的接口及特点:List(列表).Set(保证集合中元素 ...

  5. 创建MAVEN项目报错

    创建MAVEN项目pom.xml报错 Failure to transfer org.apache.maven:maven-archiver:jar:2.4.2 from http://repo.ma ...

  6. org.openqa.selenium.NoSuchElementException:

    http://www.blogjava.net/qileilove/archive/2014/12/11/421309.html selenium webdriver定位不到元素的五种原因及解决办法 ...

  7. 【CSS】CSS画矩形、圆、半圆、弧形、半圆、小三角、疑问框

    在网页中,常常会用到各种Icon,假设老是麻烦设计狮画出来不免有些不好意思,所以有时候我们也能够用CSS写出各种简单的形状.一来能够减轻他们的负担,二来也能够使用CSS替代图片.提高载入速度. 在网页 ...

  8. SQL SERVER读书笔记:nolock

    让查询语句不去申请共享锁,从而消除死锁,效果立竿见影. 缺点: 1.脏读 2.只能解决共享锁(S锁)参与的问题 3.需要修改语句本身才能使用

  9. viz.js操作流程

    1.下载依赖的js文件,并引入 <script src="${root }/resources/js/graphviz/viz.js"></script> ...

  10. poj--1274--The Perfect Stall(最大匹配)

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21665   Accepted: 973 ...