Tarjan水题系列(3):HNOI2006 潘多拉的魔盒
题目:
大意:
盒子与盒子之间的关系构成一个有向图 求图上包含节点数最多的路径的节点数
思路:
有向图上求包含节点数最多的路径的节点数 可直接使用tarjan缩点后拓扑dp求得 在此不赘述
此题重点是如何判定盒子与盒子之间的关系
首先我们要有一个共识 盒子的起点一致 一个盒子包含另一个盒子相当于它可以走另一个盒子到不了的路 换句话说 一个盒子不是另一个盒子的下属当且仅当它能够到另外一个盒子走不到的地方
而与此同时此题的数据范围非常的小 所以我们可以有一点大胆的想法
判定两只笔谁真谁伪 我们可以判断写同一个字的表现来看 许多实验检验某一物的某一性质是否相同的原理都基本含有对照的思想
我们在这里也可以如此 两个盒子同时从起点出发 同时走一样的路径 走到谁不能走或双方走完为止(边全遍历完) 通过这样便可以判断盒子之间的关系
同时注意这里的判断是单向的即i属于不属于j 并没有判断j属不属于i所以两种情况都要考虑
至此算法也已经很明显了
下面是代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <queue>
#define MAXX 55
#define r(x) x=read()
using namespace std;
int lj[MAXX][MAXX][],map[MAXX][MAXX],put[MAXX][MAXX],flag[MAXX][MAXX],
id[MAXX],sta[MAXX],dfn[MAXX],low[MAXX],dp[MAXX],w[MAXX],
pre[MAXX],flag2[MAXX],ans,top,k,num,n;
int h[MAXX],cnt;
struct edge{int to,nex;}e[MAXX];
void add(int u,int to)
{
cnt++;
e[cnt]=(edge){to,h[u]};
h[u]=cnt;
}
typedef pair<int ,int >node;
void tarjan(int now)
{
low[now]=dfn[now]=++k;
sta[++top]=now;
for(int i=h[now];i;i=e[i].nex)
{
if(!dfn[e[i].to])
tarjan(e[i].to),low[now]=min(low[now],low[e[i].to]);
else
if(!id[e[i].to])
low[now]=min(low[now],dfn[e[i].to]);
}
if(dfn[now]==low[now])
{
id[now]=++num;
while(sta[top]!=now){id[sta[top]]=num,--top;}
--top;
}
}
bool bfs(int x,int y)
{
memset(flag,,sizeof(flag));
queue<node>que;
que.push(node(,));
while(!que.empty())
{
node p;
p=que.front();que.pop();
for(int i=;i<=;++i)
{
int x1=lj[x][p.first][i],y1=lj[y][p.second][i];
if(put[x][x1]&&!put[y][y1])
return ;
else
if(!flag[x1][y1])
que.push(node(x1,y1)),flag[x1][y1]=;
}
}
return ;
}
int read()
{
char ch=;int w=;
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){w=w*+ch-'';ch=getchar();}
return w;
}
int main()
{
r(n);
for(int t=;t<=n;++t)
{
int n1=,nm=,to=;
r(n1),r(nm);
for(int i=;i<=nm;++i)
r(to),put[t][to]=;
for(int i=;i<n1;++i)
for(int j=;j<=;++j)
r(to),lj[t][i][j]=to;
}
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
if(i!=j&&bfs(i,j))
add(i,j);
for(int i=;i<=n;++i)
if(!id[i])
tarjan(i);
for(int i=;i<=n;++i)
{
w[id[i]]+=;
for(int j=h[i];j;j=e[j].nex)
if(id[i]!=id[e[j].to])
map[id[i]][id[e[j].to]]=,++pre[id[e[j].to]];
}
queue<int>que;
for(int i=;i<=num;++i)
if(!pre[i])
que.push(i),dp[i]=w[i],ans=max(dp[i],ans);
while(!que.empty())
{
int p=que.front();que.pop();
for(int i=;i<=num;++i)
if(map[p][i])
{
dp[i]=max(dp[i],dp[p]+w[i]),ans=max(dp[i],ans);
if(!flag2[i])
que.push(i),flag2[i]=;
}
flag2[p]=;
}
printf("%d",ans);
return ;
}
Tarjan水题系列(3):HNOI2006 潘多拉的魔盒的更多相关文章
- Tarjan水题系列(5):最大半连通子图 [ZJOI2007 luogu P2272]
题目 大意: 缩点后转为求最长链的长度和最长链的个数 思路: 看懂题就会做系列 长度和个数都可以拓扑排序后DP求得 毕竟是2007年的题 代码: 如下 #include <cstdio> ...
- Tarjan水题系列(4):HAOI2010 软件安装
题目: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). ...
- Tarjan水题系列(2):HNOI2012 矿场搭建
题目: 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后 ...
- Tarjan水题系列(1):草鉴定Grass Cownoisseur [USACO15JAN]or[luogu P3119]
题目如下: 约翰有n块草场,编号1到n,这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从1号草场出发,最后回到1号草场.她想经过尽可能多的草场,贝 ...
- 图论(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的最长路.. ------------------------------------- ...
- nyoj 1208——水题系列——————【dp】
水题系列 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 给你一个有向图,每条边都有一定的权值,现在让你从图中的任意一点出发,每次走的边的权值必须必上一次的权 ...
- 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 464 Solved: 221[Submit][Stat ...
- BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)
Description 传说中,有个神奇的潘多拉宝盒.如果谁能打开,便可以拥有幸福.财富.爱情.可是直到真的打开,才发现与之 相随的还有灾难.不幸.其实,在潘多拉制造这个宝盒的时候,设置了一些咒语来封 ...
随机推荐
- 【crontab】误删crontab及其恢复
中秋节快到了,首先祝自己中秋快乐. 昨天下午六点,心里正想着加完一个crontab就可以下班了.本来想执行 crontab -e的,没想到手一抖就输入了crontab ,然后就进入了下面这个样子.
- 21.栈的压入、弹出序列(python)
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- C#与JAVA的互通
C#与JAVA的互通 https://blog.csdn.net/sinat_35165183/article/details/68936910
- css-js-弹出层
HTML: <!-- 弹出层 --> <div class="popwindow" > <div class="pop" id=& ...
- forEach、map、filter、reduce的区别
1.相同点: 都会循环遍历数组中的每一项: map().forEach()和filter()方法里每次执行匿名函数都支持3个参数,参数分别是:当前元素.当前元素的索引.当前元素所属的数组: 匿名函数中 ...
- 在Linux下使用命令行打印文件
近期需要将数学笔记打印出来复习,才发现Linux KDE环境下的默认PDF软件Okular根本无法将我在GoodNotes B5大小的页面写下的内容自适应地放大到A4纸上,只能以页面的原始尺寸打印.然 ...
- 【C++】char* 和 char[] 区别的理解
string 是一个类,其中有一个 char * 类型的私有变量. 因此可以如下构建一个string类型的变量. string str = "abcd"; 其中,右值“abcd”一 ...
- xor or and 线段树
每一位维护一颗线段树 (-1)^1 =-2 (-2)^1=-1 #include <cstdio> #include<iostream> using namespace std ...
- [UPC10525]:Dove打扑克(暴力+模拟)
题目描述 $Dove$和$Cicada$是好朋友,他们经常在一起打扑克来消遣时光,但是他们打的扑克有不同的玩法. 最开始时,牌桌上会有$n$个牌堆,每个牌堆有且仅有一张牌,第$i$个牌堆里里里那个扑克 ...
- 京东面试题:Java中 ++i 的操作是线程安全的么?为什么?如何使其线程安全呢?
你真的了解volatile关键字吗?http://blog.csdn.net/FansUnion/article/details/79495080 面试题:为什么最后两行没有运行?http://blo ...