【BZOJ-1194】潘多拉的盒子 拓扑排序 + DP
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
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
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的更多相关文章
- BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )
O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...
- 图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 344 Solved: 181[Submit][Stat ...
- 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 464 Solved: 221[Submit][Stat ...
- [BZOJ1194][HNOI2006][强连通分量Tarjan+dfs]潘多拉的盒子
[BZOJ1194][HNOI2006]潘多拉的盒子 Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语 ...
- POJ 3249 拓扑排序+DP
貌似是道水题.TLE了几次.把所有的输入输出改成scanf 和 printf ,有吧队列改成了数组模拟.然后就AC 了.2333333.... Description: MR.DOG 在找工作的过程中 ...
- [NOIP2017]逛公园 最短路+拓扑排序+dp
题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...
- 洛谷P3244 落忆枫音 [HNOI2015] 拓扑排序+dp
正解:拓扑排序+dp 解题报告: 传送门 我好暴躁昂,,,怎么感觉HNOI每年总有那么几道题题面巨长啊,,,语文不好真是太心痛辣QAQ 所以还是要简述一下题意,,,就是说,本来是有一个DAG,然后后来 ...
- 【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP
[BZOJ5109][CodePlus 2017]大吉大利,晚上吃鸡! Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏 ...
- bzoj1093[ZJOI2007]最大半连通子图(tarjan+拓扑排序+dp)
Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u ...
随机推荐
- 含有ref out 参数 的方法反射 Emit 与 普通
反射中很多朋友应该屡屡被带有ref out参数的方法折腾 当使用正常反射一个方法时候: 代码如下调用一个后期绑定方法MakeByRefType 就行了 MemberInfo test = typeof ...
- Python中使用LMDB
在python中使用lmdb linux中,可以使用指令pip install lmdb安装lmdb包. 生成一个空的lmdb数据库文件 # -*- coding: utf-8 -*- import ...
- idea添加jdbc包
IDEA版本:IDEA 14 这里我使用的第三方jar包是数据库的JDBC jar包导出案例. 1.创建一个Module,名称为dataBase,在里面我们先创建一个folder用来包含所需要的jar ...
- luogu P3393 逃离僵尸岛
luoguP3393逃离_僵尸岛_ 一道洛谷不知道哪门子月赛的题 可以用此题来练习最短路算法 SPFA和dijkstra的练习题(关于Floyed,他死了 思路: 本题是最短路板子. 首先就是建立虚点 ...
- Es官方文档整理-3.Doc Values和FieldData
Es官方文档整理-3.Doc Values和FieldData 1.Doc Values 聚合使用一个叫Doc Values的数据结构.Doc Values使聚合更快.更高效且内存友好. Doc Va ...
- sql server 2000系统表sysproperties在SQL 2008中无效的问题
Sqlserver有一个扩展属性系统表sysproperties,因为只接触过MSSQL2005及以后的版本,在生产库2008版本及联机文档上搜了下都找不到这个系统表,后来发现这个系统表在2005版本 ...
- 向SQL Server 现有表中添加新列并添加描述.
注: sql server 2005 及以上支持. 版本估计是不支持(工作环境2005,2008). 工作需要, 需要向SQL Server 现有表中添加新列并添加描述. 从而有个如下存储过程. (先 ...
- Winafl学习笔记
最近在跟师傅们学习Winafl,也去搜集了一些资料,有了一些自己的理解,就此记录一下. Winafl是一个运行时插桩工具,可以提高crash的捕获率. 同时也有自己的遗传算法,可以根据代码覆盖程度进行 ...
- sql server2012 企业版 百度云下载
链接: https://pan.baidu.com/s/1j7a6RWwpvSzG-sF7Dnexfw 提取码: 关注公众号[GitHubCN]回复获取
- Winfom 插件式(Plugins)/模块化开发框架-动态加载DLL窗体-Devexpress
插件式(AddIn)架构,不是一个新名词,应用程序采用插件式拼合,可以更好的支持扩展.很多著名的软件都采用了插件式的架构,如常见的IDE:Eclipse,Visual Studio,SharpDeve ...