题面:洛谷传送门 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. faster-rcnn代码阅读1

    毫无疑问,faster-rcnn是目标检测领域的一个里程碑式的算法.本文主要是本人阅读python版本的faster-rcnn代码的一个记录,算法的具体原理本文也会有介绍,但是为了对该算法有一个整体性 ...

  2. WIN7通过批处理开启/禁用无线网卡

    哥比較懒,直接上步骤: 1.看自己的电脑是否有devcon.exe 这个软件,能够直接在WINDOWS文件夹的SYSTEM32文件夹下面搜索.也能够通过命令行RUN-----------CMD---- ...

  3. 【LeetCode OJ 136】Single Number

    题目链接:https://leetcode.com/problems/single-number/ 题目:Given an array of integers, every element appea ...

  4. 单片机project师必备的知识

    C语言编程 程序编译过程  哪部分干什么 数据结构  链表 二叉树 算法   数组  堆栈 队列算法 遍历 常量在内存中的表现形式 语法和内存的相应关系 数电 UML 类图 时序图 状态图 用例图   ...

  5. Value Stewardship Over Showmanship

     Value Stewardship Over Showmanship Barry Hawkins WHEn An ARCHiTECT EnTERS A pRojECT, there is an u ...

  6. 关于Mybatis的几个问题

    今天在用mybatis开发的时候遇到两个问题,下面一一列出并给出解决方案. 问题一 最开始我设置的实体类中有个字段如isParent为boolean类型,set和get方法是eclispe自动生成的. ...

  7. WPF中ListBox ListView数据翻页浏览笔记(强调:是数据翻页,非翻页动画)

    ListBox和ListView在应用中,常常有需求关于每页显示固定数量的数据,然后通过Timer自动或者手动翻页操作,本文介绍到的就是该动作的实现. 一.重点 对于ListBox和ListView来 ...

  8. hihoCoder-1839 榶榶榶 数学

    题面 题意:给你一个500000长度的数字,然后环形的让每位做头,例如123,就有123,231,312三个,然后问这n个数字的和S,S的最小非1因子是多少 题解:每个数字在每个位置都会有一次,如果说 ...

  9. netcore发布到centos 验证码Zkweb.system.drawing不显示及乱码的问题

    netcore发布到centos 使用的是Zkweb.system.drawing生成验证码,发布后可能会出现不显示及乱码的情况 1.验证码图片不显示(通过日志会发现生成图片时代码已经异常) Zkwe ...

  10. Hadoop MapReduce编程 API入门系列之wordcount版本2(六)

    这篇博客,给大家,体会不一样的版本编程. 代码 package zhouls.bigdata.myMapReduce.wordcount4; import java.io.IOException; i ...