2018/8/9 MultiU 6 并查集+dfs,反向建边提高查询效率 !!! / 最大字段和n维(降维)/ 状压+中途相遇法...
hdu6370 Werewolf
http://acm.hdu.edu.cn/showproblem.php?pid=6370
题意:村民只能说真话,狼人“可以”撒谎,每个人说一句话指向出自己之外任意一人身份,问与多少铁民和铁狼。
思路:1.因为可以有全狼的情况,所以不存在铁民。
2.通过基环树找狼。(具体参见下图,搬运于别人的博客QAQ。。。)
当我们发现有连续个点是有村民的边,如点1,点2,点3,点4,点5,点6;而这些个连续的其中一个点(如图中的点6)有一条狼人边连到了这些个连续的其他的点(如上图连到了点1)。
此时,我们用反证法可以证明,倘若1号点是村民,则根据村民不会说谎的性质可以判断出1到6号点全是村民,而根据村民不会说谎的性质,只能证明出1号点必为狼人。此时我们同时也可以发现,倘若1号点是狼人,则根据狼人会说谎的性质可知,指向1号点为村民的也必定是狼人。
因此我们的算法雏形就初步显现出来了。
我们要维护一些连续的村民点,可以用一个并查集进行维护。我们可以将村民边上的两个点不断的用并查集去合并,而当我们遍历狼边的时候,倘若我们发现狼边上的两个点都在一个集合中,则说明必定满足上述的情况,则我们不断遍历这条狼人边所指向的那个结点(如上图的1号点),判断有多少条指向它的村民边即可。(此处我们可以将村民边反向建立,这样可以让我们高效的查询)。
参考题解:https://blog.csdn.net/weixin_39453270/article/details/81515570
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e5+5; 5 typedef pair<int, int> pii; 6 vector<int> vi[N]; 7 vector<pii>wolf; 8 int p[N],n; 9 10 void init(){ 11 for(int i=0;i<=n;i++) p[i]=i, vi[i].clear(); 12 wolf.clear(); 13 } 14 int root(int x){ 15 while(p[x]!=x) x=p[x]; 16 return x; 17 } 18 bool same(int x, int y){ 19 return root(x) == root(y); 20 } 21 void unit(int x, int y){ 22 int tmp1 = root(x), tmp2 = root(y), cur; 23 if(tmp1 == tmp2) return; 24 p[tmp2] = tmp1; 25 while(y != tmp1){ 26 cur = p[y]; 27 p[y] = tmp1; 28 y = cur; 29 } 30 } 31 int ans; 32 void dfs(int x){ 33 int sz = vi[x].size(); 34 for(int i = 0; i < sz; i++){ 35 ans++; 36 dfs(vi[x][i]); 37 } 38 } 39 40 int main() 41 { 42 int t, x; 43 char s[20]; 44 scanf("%d", &t); 45 while(t--){ 46 scanf("%d", &n); 47 init(); 48 for(int i = 1; i <= n; i++){ 49 scanf("%d %s", &x, s); 50 if(s[0] == 'w'){ 51 wolf.push_back(make_pair(i, x));///inverse. 52 } 53 else{ 54 vi[x].push_back(i); 55 unit(x, i); 56 } 57 } 58 ans = 0; 59 int sz = wolf.size(); 60 for(int i = 0; i < sz; i++){ 61 if(same(wolf[i].first, wolf[i].second)){ 62 ans++; 63 dfs(wolf[i].second); 64 } 65 } 66 printf("0 %d\n", ans); 67 } 68 return 0; 69 }
View Code
打多校的几场下来,就是a完水题就挂机,然后赛后看题解,有的时候看完题解还是不知道该怎么写,于是看别人的代码,于是于是。。。依然啥也不会。。。(怨念。。o(一︿一+)o)
颓废度日,看底特律到睡着后决定补大白上的题然后。。。QAQ。。。lrj太强了!!!伏地膜!!!啊啊啊啊啊人家写出来的程序怎么这么xxxxxxx!!!x~
uva10755 G - Garbage Heap
题意:求解最大子“立方体”和。
思路:三位最大子段和,降维->二维,暴力枚举子矩阵O(n^4),第三维度采取最大子段和O(n)的dp解决,总复杂度O(n^5)。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 const int N = 20 + 5; 6 const ll inf = 1ll<<60;/// 7 ll S[N][N][N]; 8 int a, b, c, b0, b1, b2; 9 10 void expand(int i, int& b0, int& b1, int& b2){ 11 b0 = i&1; i >>= 1; 12 b1 = i&1; i >>= 1; 13 b2 = i&1; 14 } 15 int sign(int b0, int b1, int b2){ return (b0+b1+b2)&1? 1: -1;} 16 17 ll sum(int x1, int x2, int y1, int y2, int z1, int z2){ 18 int dx = x2-x1+1, dy = y2-y1+1, dz = z2-z1+1; 19 ll s = 0; 20 for(int i = 0; i < 8; i++){ 21 expand(i, b0, b1, b2); 22 s -= S[x2-b0*dx][y2-b1*dy][z2-b2*dz] * sign(b0, b1, b2); 23 } 24 return s; 25 } 26 27 int main() 28 { 29 int t; 30 scanf("%d", &t); 31 while(t--){ 32 scanf("%d %d %d", &a, &b, &c); 33 for(int i = 1; i <= a; i++) for(int j = 1; j <= b; j++) for(int k = 1; k <= c; k++) scanf("%lld", &S[i][j][k]); 34 for(int x = 1; x <= a; x++){ 35 for(int y = 1; y <= b; y++){ 36 for(int z = 1; z <= c; z++){ 37 for(int i = 1; i <= 7; i++){ 38 expand(i, b0, b1, b2); 39 S[x][y][z] += S[x-b0][y-b1][z-b2] * sign(b0,b1,b2); 40 } 41 } 42 } 43 } 44 ll ans = -inf, s;///... 45 for(int x1 = 1; x1 <= a; x1++){ 46 for(int x2 = x1; x2 <= a; x2++){ 47 for(int y1 = 1; y1 <= b; y1++){ 48 for(int y2 = y1; y2 <= b; y2++){ 49 ll M = 0; 50 for(int z = 1; z <= c; z++){ 51 s = sum(x1, x2, y1, y2, 1, z); 52 ans = max(ans, s - M); 53 M = min(M, s);///M<=0~~~ 54 } 55 } 56 } 57 } 58 } 59 printf("%lld\n", ans); 60 if(t) puts("");///PE... 61 } 62 return 0; 63 }
View Code
学习了lrj 的程序,思路清晰,解法实用有效,很容易将问题推广到四维或更高维度的情形。
H - Jurassic Remains(UVALive - 2965)
题意:n(<=24 24/2=12可状压)个字符串,选尽量多个串使得每个大写字母(26个字母, 可状压)都出现偶数次。
思路:1.将每个串转化为二进制,出现偶数次即为该位xor后为0。
2.将字符串集合划分为两个集合,也转化为二进制,则有AxorB=0 -> A = B。(A、B为两集合中所有二进制异或和)。
3.对于每个A=B,找到包含字符串数目最多(二进制中1最多->bitcount最大)的集合,这些集合中bitcount最大的集合即为答案~
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 24; 5 int A[N]; 6 map<int, int> table; 7 char s[1000]; 8 9 int bitcount(int i){ return i == 0? 0: bitcount(i>>1) + (i&1);} 10 11 int main() 12 { 13 int n, x; 14 while(~scanf("%d", &n)){ 15 memset(A, 0, sizeof(A)); 16 table.clear(); 17 for(int i = 0; i < n; i++){ 18 scanf("%s", s); 19 for(int j = 0; s[j]; j++) A[i] ^= (1<<(s[j]-'A')); 20 } 21 int n1 = n>>1; 22 int n2 = n - n1, N1 = (1<<n1); 23 for(int i = 0; i < N1; i++){ 24 x = 0; 25 for(int j = 0; j < n1; j++) if(i & (1<<j)) x ^= A[j]; 26 if(!table[x] || (bitcount(table[x]) < bitcount(i))) table[x] = i; 27 } 28 int ans = 0, N2 = (1<<n2); 29 for(int i = 0; i < N2; i++){ 30 x = 0; 31 for(int j = 0; j < n2; j++) if(i & (1<<j)) x ^= A[j+n1]; 32 if(table[x] && bitcount(ans) < bitcount(i) + bitcount(table[x])) ans = (i<<n1)|table[x];///both | and ^ are right and fast~ 33 } 34 printf("%d\n", bitcount(ans)); 35 for(int i = 0; i < n; i++) if(ans & (1<<i)) printf("%d ", i+1); 36 puts(""); 37 } 38 return 0; 39 }
(・∀・(・∀・(・∀・*)
emm...莫名喜欢状压(x).
转载于:https://www.cnblogs.com/curieorz/p/9447454.html
2018/8/9 MultiU 6 并查集+dfs,反向建边提高查询效率 !!! / 最大字段和n维(降维)/ 状压+中途相遇法...相关推荐
- HDU6411 带劲的and和(2018百度之星复赛,并查集,位运算,思路)
Problem Description 度度熊专门研究过"动态传递闭包问题",他有一万种让大家爆蛋的方法:但此刻,他只想出一道简简单单的题--至繁,归于至简. 度度熊有一张n个点m ...
- Jumping Monkey 并查集,反向思维
题意 : n点的树,每个点的点权distinct,求分别从每个点出发能到达的点数(被到达的点必须是路径上点权最大的点) 思路 : 考虑点权最大的那个结点(假设为u),显然不管从哪个结点开始跳一次,都可 ...
- zoj 3761 Easy billiards 并查集+dfs
生活真是奇妙的东西,这样的题目居然能被联想到这样的算法,只能说智商不够啊. 这道题目的意思不解释了,月赛的时候我队友已经想出来了做法,但是我们最后还是没A. 题解: 1.首先将所有能连接的球连接起来, ...
- 【无码专区9】序列统计(带权并查集 + 前缀和建边 + dp)
因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...
- [COCI2017-2018#5] Pictionary(并查集+dfs)
贼ex的一道,卡了本仙女整整7个小时orz 思路容易理解,but码力very重要orz 我愿意花五毛钱提升我的码力,换个脑子也行,不换脸这张脸生得俊俏 luogu传送door 题目 在宇宙一个不为人知 ...
- UVA - 208 Firetruck(并查集+dfs)
题目: 给出一个结点d和一个无向图中所有的边,按字典序输出这个无向图中所有从1到d的路径. 思路: 1.看到紫书上的提示,如果不预先判断结点1是否能直接到达结点d,上来就直接dfs搜索的话会超时,于是 ...
- 【51Nod - 1416】两点 (dfs 或 并查集+dfs)
题干: 福克斯在玩一款手机解迷游戏,这个游戏叫做"两点".基础级别的时候是在一个n×m单元上玩的.像这样: 每一个单元有包含一个有色点.我们将用不同的大写字母来表示不同的颜 ...
- Multiplayer Moo[ [ 并查集+dfs连通块 ] / [ dfs ] ]
题目链接 题目描述: The cows have come up with a creative new game, surprisingly giving it the least creative ...
- HDU1181:变形课(并查集 + DFS + BFS)
变形课 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submissi ...
最新文章
- 唐筛的准确率这么低为什么还要做_做注塑这么苦,为什么你还要坚持?
- nowcoder 202F-平衡二叉树
- python创建模块文件夹_python文件、文件夹、压缩包处理模块-shutil模块
- 分布式技术追踪 2017年第四期
- Linux网络深入DHCP、FTP原理和配置方法(详细图解)
- phpexcel 导出循环增加列数_基于.NetCore3.1搭建项目系列 —— 使用Swagger导出文档 (补充篇)...
- QOMO Linux 4.0 正式版发布
- 解决方案_环网柜监测解决方案
- 关于redis的pipline和lua脚本
- bartender实现即扫即打印功能扫描完后自动打印_日本彩色激光打印机推荐人气排名15款...
- Hadoop 源码目录树
- bzoj1046 [HAOI2007]上升序列
- System.Windows.Forms.Application.DoEvents();
- Jquery.min.js 下载
- netstat命令详解Linux,Linux netstat命令详解
- 可作为工质状态参数的是_§2工质的热力状态及其基本状态参数
- java转行能做什么_java转行可以做什么?应该如何去考虑?
- js实现form的submit请求
- 算法系列——贝尔曼福特算法(Bellman-Ford)
- 双能CT的基本原理及理解笔记