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


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
题目大意:咒语机中的元件每个都有两种情况,即把信号处理后把信号传给两个对应的元件,若信号传给了输出元件,那么就可以得到一个种类的信号。设每个咒语机可以产生若干种信号,那么找到一个最长上升序列使得序列中的每一个咒语机都能生成他之前每一个咒语机能生成的信号。
大概思路:我们可以先枚举两个咒语机之间的关系(比如咒语机a产生的信号种类数比咒语机b产生的信号种类数多),即让两个咒语机都一直向添加1移动或一直向添加0移动,若某个咒语机搜索时先遇到输出机,那么这个咒语机产生的信号种类一定比另一个多。枚举时按照a属于b的关系建立单向边。然后Tarjan缩点找最长链即可。
AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int S,a,b,f,cnt,dfs_num,CN,top,re_cnt,maxn=;
int pre[],dye[],DFN[],LOW[],size[],in_tow[],tow[],re_pre[],ans[];
int print[][],jdg[][];
int move[][][];
struct pack{int from,to,next;} E[],re_E[];
void add_edge(int x,int y){
E[++cnt].to=y;
E[cnt].next=pre[x];
E[cnt].from=x;
pre[x]=cnt;
}
void rebuild(){
for(int i=;i<=S;++i)
for(int j=pre[i];j;j=E[j].next)
if(dye[i]!=dye[E[j].to]){
re_E[++re_cnt].to=dye[E[j].to];
re_E[re_cnt].next=re_pre[dye[i]];
re_E[re_cnt].from=dye[i];
re_pre[dye[i]]=re_cnt;
}
}
void dfs(int p,int q){
if(jdg[p][q]||f) return ;
jdg[p][q]=;
if(print[b][q]&&!print[a][p]) {f=;return ;}
dfs(move[a][p][],move[b][q][]);
dfs(move[a][p][],move[b][q][]);
}
int check(){
f=;memset(jdg,,sizeof(jdg));
dfs(,);
return !f;
}
void tarjan(int pos){
DFN[pos]=LOW[pos]=++dfs_num;
in_tow[tow[++top]=pos]=;
for(int i=pre[pos];i;i=E[i].next){
if(!DFN[E[i].to]){
tarjan(E[i].to);
LOW[pos]=min(LOW[pos],LOW[E[i].to]);
}
else if(in_tow[E[i].to])
LOW[pos]=min(LOW[pos],DFN[E[i].to]);
}
if(DFN[pos]==LOW[pos]){
in_tow[pos]=;
size[dye[pos]=++CN]++;
while(pos!=tow[top]){
size[dye[tow[top]]=CN]++;
in_tow[tow[top--]]=;
}
--top;
}
}
int req(int v){
if(ans[v]) return ans[v];
ans[v]=size[v];
for(int i=re_pre[v];i;i=re_E[i].next)
ans[v]=max(ans[v],req(re_E[i].to)+size[v]);
return ans[v];
}
int find_max(){
for(int i=;i<=CN;++i) maxn=max(maxn,req(i));
return maxn;
}
int main(){
scanf("%d",&S);
for(int i=;i<=S;++i){
int n,m;
scanf("%d%d",&n,&m);
for(int j=;j<=m;++j){
int t;
scanf("%d",&t);
print[i][t+]=;
}
for(int j=;j<=n;++j){
int t,tt;
scanf("%d%d",&t,&tt);
move[i][j][]=t+;
move[i][j][]=tt+;
}
}
for(int i=;i<=S;++i)
for(int j=;j<=S;++j)
if(i!=j){
a=i;
b=j;
if(check()) add_edge(i,j);
}
for(int i=;i<=S;++i)
if(!dye[i])
tarjan(i);
rebuild();
printf("%d",find_max());
return ;
}
[BZOJ1194][HNOI2006][强连通分量Tarjan+dfs]潘多拉的盒子的更多相关文章
- 强连通分量(tarjan求强连通分量)
双DFS方法就是正dfs扫一遍,然后将边反向dfs扫一遍.<挑战程序设计>上有说明. 双dfs代码: #include <iostream> #include <cstd ...
- 图论(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的最长路.. ------------------------------------- ...
- 求图的强连通分量--tarjan算法
一:tarjan算法详解 ◦思想: ◦ ◦做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间 ...
- 【有向图】强连通分量-Tarjan算法
好久没写博客了(都怪作业太多,绝对不是我玩的太嗨了) 所以今天要写的是一个高大上的东西:强连通 首先,是一些强连通相关的定义 //来自度娘 1.强连通图(Strongly Connected Grap ...
- 【BZOJ-1194】潘多拉的盒子 拓扑排序 + DP
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 456 Solved: 215[Submit][Stat ...
- 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 464 Solved: 221[Submit][Stat ...
- 【强连通分量】Bzoj1194 HNOI2006 潘多拉的盒子
Description Sulotion 首先要对每对咒语机建图,判断机器a是否能生成所有机器b生成的 如果跑一个相同的串,最后结束的点b可输出a不可输出,判断就为否 大概就用这种思路,f[x][y] ...
- BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)
Description 传说中,有个神奇的潘多拉宝盒.如果谁能打开,便可以拥有幸福.财富.爱情.可是直到真的打开,才发现与之 相随的还有灾难.不幸.其实,在潘多拉制造这个宝盒的时候,设置了一些咒语来封 ...
随机推荐
- mysql5.6版本修改密码
UPDATE user SET Password=PASSWORD('新密码') WHERE User='root';
- C#学习笔记----静态字段和静态方法
1.使用关键字 static 修饰的字段或方法成为静态字段和静态方法,如 public static int num = 1;2.静态字段属于类,并为类所用.而非静态字段属于对象,只能被特定的对象专有 ...
- 【POJ 2387 Til the Cows Come Home】
Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 59755Accepted: 20336 Description Bessie is ...
- 刷新iframe
<button onclick="document.getElementById('frame').contentWindow.location.reload(true)"& ...
- 如何从oracle官网中下载The java language specification(java 语言规范)
第一步: 第二步: 第三步:下面这个图在这个页面的下方,所以你只要一直往下看,直到看到下图的文字为止: 第四步: 第五步: 这样你就可以成功下载该java 语言规范的pdf了. 它直接下载的网址为: ...
- Linux下hdparm硬盘测速
在Linux下可以使用hdparm对硬盘进行测试或者查看硬盘的相关信息.这样你就知道了硬盘读写速度. Hdparm功能说明:显示与设定硬盘的参数. 语 法:hdparm [-CfghiIqtTvyYZ ...
- linux fg bg ctrl + z jobs & 等命令
fg.bg.jobs.&.ctrl + z都是跟系统任务有关的,虽然现在基本上不怎么需要用到这些命令,但学会了也是很实用的一.& 最经常被用到这个用在一个命令的最后,可以把这个命令放到 ...
- 为什么说for循环设置循环变量的那部分是一个父作用域?
最近在看阮一峰老师的<ES6> 看到let时,发现一处for循环很神奇的地方. 书中的原话是:“另外,for循环还有一个特别之处,就是设置变量的那部分是一个父作用域,而循环体内部是一个单独 ...
- 转:mysql grant
本文实例,运行于 MySQL 5.0 及以上版本. MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删 ...
- 阿里云Centos 7 FTP(vsftp)服务安装及配置
#检查vsftpd是否安装 rpm -qa | grep vsftpd #检查vsftpd版本并安装 yum list vsftpd yum install vsftpd #设置开机启动 system ...