POJ3660 Cow Contests,TYVJ2024 运动员身高
2016-04-01 15:54
281 查看
Bitset Closure
poj3660Memory: 388K Time: 16MS
https://code.csdn.net/snippets/1631904
tyvj2024
消耗时间 46 ms 消耗内存 1000 KiB
https://code.csdn.net/snippets/1631905
概述
这两道题基本完全一样,具体题意可以直接看tyvj上的汉语题tyvj代码直接从poj上改的,增大maxn到2000,再添加一个数组当队列记录方案即可。
算法
//以下针对tyvj只要满足 比i高的人数+比i矮的人数+1=n,那么这个人就可以被确定。
如果把A比B高看作从A->B连一条有向边,则X比Y高的充要条件就是X能到达Y。
所以比i高的人数就是能到达i的人数,比i矮的人数就是i能到达的人数(均不包括i),这可以通过看联通矩阵[…][i]和[i][…](在代码
38行到
42行)确定
怎么求联通矩阵?这就是传递闭包问题了。
化用Floyd:
for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) reach[i][j]|=(reach[i][k]&reach[k][j]);
这就足以通过这道题了
不过可以有一个常数优化
可以发现,前两层循环k, i以后,
reach[i][k]就能确定了。如果它是false,那后面
reach[i][k]&reach[k][j]肯定也是假,不用再循环了,直接
continue
代码变成了:
for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) { if(!reach[i][k]) continue; for(int j=1; j<=n; ++j) reach[i][j]|=reach[k][j]; }
然后,看到内层循环是把reach[i]和reach[k]按位或,而reach[x]可以看作一个行0-1向量组,就一个长二进制数。
于是,把原来的
bool reach[maxn][maxn];直接改成
bitset<maxn> reach[maxn];
代码变成:
for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) if(reach[i][k]) reach[i]|=reach[k];
这样做不仅巨省空间(一字节一个bool变成一位一bool,空间复杂度大约是原来的18),而且省时间(以前一位一位手动或运算,现在伟大的
bitset帮助我们拆成一个个int按位或)
时:O(132n3) ,空:O(18n2) (这俩算对了么?求验证)
其他的算法
来自tyvj题解(等待研究)考虑到n只有1000,所以建两个图,一个原图,一个反向图,对于一个点i,做两次dfs,即可求出比i高和比i矮的人数,验证一下就可以了,复杂度O(n^2)
这位大神能不能再具体一点..还有,复杂度真的正常吗..
遇到的问题
一开始做tyvj上那道题,按自己的思路写了一个程序,总是WA最后一个点我的思路:拓扑排序,如果没有入边的点只有一个,则这个点一定可以确定,删除这个点,加入答案,如果没有出边的点只有一个,也删除这个点,加入答案,如此循环直到不再能删下去为止。
多亏最后一个点啊(T_T)否则我真发现不了这个算法的漏洞
画了一张图解释下:
如图所示,不存在唯一出度为零的点,也不存在唯一入度为零的点,算法结束。但是中间蓝色的点,很明显无论左边两个点谁先谁后,都在它前面,它肯定是第4名。如果按照正确的思路,中间三个点因为都满足比它大的和比它小的点把它稳定地“夹”起来,所以它们都是可以确定的点。
谨此。
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- 用单调栈解决最大连续矩形面积问题
- 2632 Crashing Robots的解决方法
- 1573 Robot Motion (简单题)
- POJ 1200 Crazy Search(简单哈希)
- 【高手回避】poj3268,一道很水的dijkstra算法题