1194: [HNOI2006]潘多拉的盒子

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 456  Solved: 215
[Submit][Status][Discuss]

Description

Input

第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50)。文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述。每一块的格式如下。
一块的第一行有两个正整数n,m。分别表示该咒语机中元件的个数、咒语源输出元的个数(1≤m≤n≤50)。
接下来一行有m个数,表示m个咒语源输出元的标号(都在0到n-1之间)。接下来有n行,每一行两个数。第i行(0≤i≤n-1)的两个数表示pi,0和pi,1(当然,都在0到n-1之间)。

Output

第一行有一个正整数t,表示最长升级序列的长度。

Sample Input

4
1 1
0
0 0
2 1
0
1 1
0 0
3 1
0
1 1
2 2
0 0
4 1
0
1 1
2 2
3 3
0 0

Sample Output

3

HINT

Source

Solution

这道题还是比较有趣的..如果能够得到包含关系,可以直接拓扑排序dp求解最长链。

然后如何判断是否包含?需要利用自动机的相关性质。

考虑dp,$f[x][y]$表示自动机1和自动机2分别对应状态$x$和$y$,然后枚举转移更新$f[x'][y']$。

考虑什么情况不满足包含,即$f[x][y]=1$且$end[x]=1$且$end[y]=0$表示不包含,否则一定包含。

所以只要暴力的去枚举两两自动机跑即可,主要的思想就是去尝试构造01串使得一个能匹配另一个不能。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int T,N,M;
struct DFANode{
int son[55][2],end[55];
}DFA[55],A,B;
bool f[55][55],flag; inline void Run(int x,int y)
{
if (!x || !y || f[x][y] || !flag) return;
f[x][y]=1;
if (!A.end[x] && B.end[y]) flag=0;
for (int i=0; i<=1; i++)
Run(A.son[x][i],B.son[y][i]);
}
inline bool Check(DFANode x,DFANode y)
{
memset(f,0,sizeof(f));
A=x,B=y; flag=1;
Run(1,1);
return flag;
} struct GraphNode{
struct EdgeNode{
int next,to;
}edge[55*55];
int head[55],cnt;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v);}
}G1,G2; int visit[55],stack[55],top,dfn[55],low[55],dfsn;
int belong[55],size[55],scc;
inline void Tarjan(int x)
{
visit[x]=1; stack[++top]=x;
dfn[x]=low[x]=++dfsn;
for (int i=G1.head[x]; i; i=G1.edge[i].next)
if (!dfn[G1.edge[i].to])
Tarjan(G1.edge[i].to),low[x]=min(low[x],low[G1.edge[i].to]);
else
if (visit[G1.edge[i].to]) low[x]=min(dfn[G1.edge[i].to],low[x]);
if (dfn[x]==low[x]) {
int tops=0;
scc++;
while (tops!=x) {
tops=stack[top--];
belong[tops]=scc,visit[tops]=0,size[scc]++;
}
}
}
inline void Tarjan() {for (int i=1; i<=T; i++) if (!dfn[i]) Tarjan(i);} int mp[55][55],d[55];
inline void Rebuild()
{
for (int x=1; x<=T; x++)
for (int i=G1.head[x]; i; i=G1.edge[i].next)
if (belong[x]!=belong[G1.edge[i].to])
G2.InsertEdge(belong[x],belong[G1.edge[i].to]),d[belong[G1.edge[i].to]]++;
} queue<int>q;
int dp[55];
inline void Toposort()
{
for (int i=1; i<=scc; i++) if (!d[i]) q.push(i);
for (int i=1; i<=scc; i++) dp[i]=size[i];
while (!q.empty()) {
int now=q.front(); q.pop();
for (int i=G2.head[now]; i; i=G2.edge[i].next) {
dp[G2.edge[i].to]=max(dp[G2.edge[i].to],dp[now]+size[G2.edge[i].to]);
if (!--d[G2.edge[i].to]) q.push(G2.edge[i].to);
}
}
} int main()
{
T=read();
for (int i=1; i<=T; i++) {
N=read(),M=read();
for (int x,j=1; j<=M; j++)
x=read()+1,DFA[i].end[x]=1;
for (int j=1; j<=N; j++)
DFA[i].son[j][0]=read()+1,DFA[i].son[j][1]=read()+1;
}
for (int i=1; i<=T; i++)
for (int j=1; j<=T; j++)
if (i!=j && Check(DFA[i],DFA[j]))
G1.InsertEdge(i,j);
Tarjan();
Rebuild();
Toposort();
int ans=0;
for (int i=1; i<=scc; i++) ans=max(ans,dp[i]);
printf("%d\n",ans);
return 0;
}

【BZOJ-1194】潘多拉的盒子 拓扑排序 + DP的更多相关文章

  1. BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )

    O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...

  2. 图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子

    1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 344  Solved: 181[Submit][Stat ...

  3. 1194: [HNOI2006]潘多拉的盒子

    1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 464  Solved: 221[Submit][Stat ...

  4. [BZOJ1194][HNOI2006][强连通分量Tarjan+dfs]潘多拉的盒子

    [BZOJ1194][HNOI2006]潘多拉的盒子 Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语 ...

  5. POJ 3249 拓扑排序+DP

    貌似是道水题.TLE了几次.把所有的输入输出改成scanf 和 printf ,有吧队列改成了数组模拟.然后就AC 了.2333333.... Description: MR.DOG 在找工作的过程中 ...

  6. [NOIP2017]逛公园 最短路+拓扑排序+dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...

  7. 洛谷P3244 落忆枫音 [HNOI2015] 拓扑排序+dp

    正解:拓扑排序+dp 解题报告: 传送门 我好暴躁昂,,,怎么感觉HNOI每年总有那么几道题题面巨长啊,,,语文不好真是太心痛辣QAQ 所以还是要简述一下题意,,,就是说,本来是有一个DAG,然后后来 ...

  8. 【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP

    [BZOJ5109][CodePlus 2017]大吉大利,晚上吃鸡! Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏 ...

  9. bzoj1093[ZJOI2007]最大半连通子图(tarjan+拓扑排序+dp)

    Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u ...

随机推荐

  1. webpack4.5.0+vue2.5.16+vue-loader 实战组件化开发案例以及版本问题中踩的一些大坑!!!

    一 vue-loader 我们先不管脚手架,只说vue-loader,简单讲就是可将.vue文件打包,实现组件化开发,即一个.vue文件就是一个组件,开发中只需要引入这个.vue组件就可以了! 然后. ...

  2. 洛谷 P3307: bzoj 3202: [SDOI2013] 项链

    题目传送门:洛谷P3307.这题在bzoj上是权限题. 题意简述: 这题分为两个部分: ① 有一些珠子,每个珠子可以看成一个无序三元组.三元组要满足三个数都在$1$到$m$之间,并且三个数互质,两个珠 ...

  3. Wannacry样本取证特征与清除

    一.取证特征 1)网络域名特征 http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com 2)文件特征 母体文件 mssecsvc.exe c: ...

  4. 【算法】Base64编码

    1.说明 Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法. 2.编码 ASCII码 -> 十六进制码 -> ...

  5. 去除TFS版本控制

    对于曾经做过TFS版本控制的项目,在版本控制服务不可用的时候,依然会在每次打开项目的时候都提示:当前项目是版本控制的项目,但是当前版本控制不可用,balabala的信息,如果是需要进行版本控制的项目在 ...

  6. Splay算法摘要

    先介绍变量定义 int n; struct Node { //Splay节点定义 ],val,num,siz; //fa:它爸爸:son它儿子,左0右1:val:这个节点的值 //num:这个值的数量 ...

  7. vue总结 02指令

    指令 v-text 预期:string 详细: 更新元素的 textContent.如果要更新部分的 textContent ,需要使用 {{ Mustache }} 插值. 示例: <span ...

  8. gcc/g++ 命令

    gcc & g++现在是gnu中最主要和最流行的c & c++编译器 .g++是c++的命令,以.cpp为主,对于c语言后缀名一般为.c.这时候命令换做gcc即可.其实是无关紧要的.其 ...

  9. (一)SpringMVC

    第一章 问候SpringMVC 第一节 SpringMVC简介 SpringMVC是一套功能强大,性能强悍,使用方便的优秀的MVC框架 下载和安装Spring框架: 登录http://repo.spr ...

  10. C#比较时分秒大小,终止分钟默认加十分钟,解决跨天、跨月、跨年的情况

    private void cmbInHostimes_SelectedIndexChanged(object sender, EventArgs e) { DataRow[] dr; if (chkM ...