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维(降维)/ 状压+中途相遇法...相关推荐

  1. HDU6411 带劲的and和(2018百度之星复赛,并查集,位运算,思路)

    Problem Description 度度熊专门研究过"动态传递闭包问题",他有一万种让大家爆蛋的方法:但此刻,他只想出一道简简单单的题--至繁,归于至简. 度度熊有一张n个点m ...

  2. Jumping Monkey 并查集,反向思维

    题意 : n点的树,每个点的点权distinct,求分别从每个点出发能到达的点数(被到达的点必须是路径上点权最大的点) 思路 : 考虑点权最大的那个结点(假设为u),显然不管从哪个结点开始跳一次,都可 ...

  3. zoj 3761 Easy billiards 并查集+dfs

    生活真是奇妙的东西,这样的题目居然能被联想到这样的算法,只能说智商不够啊. 这道题目的意思不解释了,月赛的时候我队友已经想出来了做法,但是我们最后还是没A. 题解: 1.首先将所有能连接的球连接起来, ...

  4. 【无码专区9】序列统计(带权并查集 + 前缀和建边 + dp)

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...

  5. [COCI2017-2018#5] Pictionary(并查集+dfs)

    贼ex的一道,卡了本仙女整整7个小时orz 思路容易理解,but码力very重要orz 我愿意花五毛钱提升我的码力,换个脑子也行,不换脸这张脸生得俊俏 luogu传送door 题目 在宇宙一个不为人知 ...

  6. UVA - 208 Firetruck(并查集+dfs)

    题目: 给出一个结点d和一个无向图中所有的边,按字典序输出这个无向图中所有从1到d的路径. 思路: 1.看到紫书上的提示,如果不预先判断结点1是否能直接到达结点d,上来就直接dfs搜索的话会超时,于是 ...

  7. 【51Nod - 1416】两点 (dfs 或 并查集+dfs)

    题干: 福克斯在玩一款手机解迷游戏,这个游戏叫做"两点".基础级别的时候是在一个n×m单元上玩的.像这样:     每一个单元有包含一个有色点.我们将用不同的大写字母来表示不同的颜 ...

  8. Multiplayer Moo[ [ 并查集+dfs连通块 ] / [ dfs ] ]

    题目链接 题目描述: The cows have come up with a creative new game, surprisingly giving it the least creative ...

  9. HDU1181:变形课(并查集 + DFS + BFS)

    变形课 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submissi ...

最新文章

  1. 唐筛的准确率这么低为什么还要做_做注塑这么苦,为什么你还要坚持?
  2. nowcoder 202F-平衡二叉树
  3. python创建模块文件夹_python文件、文件夹、压缩包处理模块-shutil模块
  4. 分布式技术追踪 2017年第四期
  5. Linux网络深入DHCP、FTP原理和配置方法(详细图解)
  6. phpexcel 导出循环增加列数_基于.NetCore3.1搭建项目系列 —— 使用Swagger导出文档 (补充篇)...
  7. QOMO Linux 4.0 正式版发布
  8. 解决方案_环网柜监测解决方案
  9. 关于redis的pipline和lua脚本
  10. bartender实现即扫即打印功能扫描完后自动打印_日本彩色激光打印机推荐人气排名15款...
  11. Hadoop 源码目录树
  12. bzoj1046 [HAOI2007]上升序列
  13. System.Windows.Forms.Application.DoEvents();
  14. Jquery.min.js 下载
  15. netstat命令详解Linux,Linux netstat命令详解
  16. 可作为工质状态参数的是_§2工质的热力状态及其基本状态参数
  17. java转行能做什么_java转行可以做什么?应该如何去考虑?
  18. js实现form的submit请求
  19. 算法系列——贝尔曼福特算法(Bellman-Ford)
  20. 双能CT的基本原理及理解笔记

热门文章

  1. 运营商主动关闭WLAN热点背后:关键是找准产业位置
  2. 《Nmap渗透测试指南》—第2章2.2节使用Zenmap进行扫描
  3. sessionID的本质
  4. 掌握jQuery插件开发,这篇文章就够了
  5. Socket网络协议之一
  6. sqlite 日期字段操作
  7. ECharts - 极坐标系下的堆叠柱状图
  8. 一些Xcode快捷键,给新手
  9. jupyter安装出现问题:安装后无法打开
  10. SQL入门(3):定义约束/断言assertion/触发器trigger