模版
合并集合
836. 合并集合 -
AcWing题库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;const int N = 1e5 + 10 ;int p[N];int n, m;int find (int x) { if (x != p[x]) p[x] = find (p[x]); return p[x]; } void Merge (int a, int b) { int pa = find (a), pb = find (b); if (pa != pb) p[pa] = pb; } string Query (int a, int b) { if (find (a) == find (b)) return "Yes" ; else return "No" ; } int main () { cin >> n >> m; for (int i = 1 ; i <= n; i++) p[i] = i; while (m--) { char x; int a, b; cin >> x >> a >> b; if (x == 'M' ) Merge (a, b); else cout << Query (a, b) << '\n' ; } return 0 ; }
应用
食物链
240. 食物链 -
AcWing题库
与根节点一共有三种关系,用0表示和根节点是同类;1表示根节点吃该结点;2表示该结点吃根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 #include <bits/stdc++.h> using namespace std;const int N = 5e4 + 10 ;int p[N], d[N];int n, k, res;int find (int x) { if (x != p[x]) { int t = find (p[x]); d[x] += d[p[x]]; p[x] = t; } return p[x]; } bool D1 (int x, int y) { int px = find (x), py = find (y); if (px != py) { p[px] = py; d[px] = d[y] - d[x]; return true ; } else { if ((d[y] - d[x] + 3 ) % 3 ) return false ; else return true ; } } bool D2 (int x, int y) { int px = find (x), py = find (y); if (px != py) { p[px] = py; d[px] = (d[y] - d[x] - 1 + 3 ) % 3 ; return true ; } else { if ((d[x] - d[y] + 1 + 3 ) % 3 ) return false ; else return true ; } } int main () { cin >> n >> k; for (int i = 1 ; i <= n; i++) p[i] = i; while (k--) { int c, x, y; cin >> c >> x >> y; if (x > n || y > n) { res++; continue ; } if (c == 1 ) if (!D1 (x, y)) res++; if (c == 2 ) if (!D2 (x, y)) res++; } cout << res; return 0 ; }
格子游戏
1250. 格子游戏
- AcWing题库
将二维变成一维\((x,y)=x*n+y\)
将一条线的两端加入一个联通块,如果发现已经在一个联通块说明形成闭环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;const int N = 200 * 200 + 10 ;int p[N];int n, m;int find (int x) { if (x != p[x]) p[x] = find (p[x]); return p[x]; } int main () { cin >> n >> m; for (int i = 1 ; i <= n * n; i++) p[i] = i; for (int i = 1 ; i <= m; i++) { int a, b; char c; cin >> a >> b >> c; int x = (a - 1 ) * n + b, y; if (c == 'D' ) y = a * n + b; else y = (a - 1 ) * n + b + 1 ; int px = find (x), py = find (y); if (px == py) { cout << i; return 0 ; } else p[px] = py; } cout << "draw" ; return 0 ; }
程序自动分析
237.
程序自动分析 - AcWing题库
因为数据量很大,但实际上没有那么多的数据,所以需要离散化
将相等的放在同一个联通块中,再遍历不相等的,如果发现不相等的两个节点在同一个联通块就输出“NO”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <bits/stdc++.h> using namespace std;const int N = 1e6 + 10 ;int p[N];int t, n, idx;typedef pair<int , int > PII;vector<PII> e, ue; unordered_map<int , int > H; int find (int x) { if (x != p[x]) p[x] = find (p[x]); return p[x]; } int Hash (int x) { if (!H.count (x)) H[x] = ++idx; return H[x]; } int main () { cin >> t; while (t--) { bool flag = true ; H.clear (), e.clear (), ue.clear (); cin >> n; for (int i = 1 ; i <= n; i++) { int a, b, c; cin >> a >> b >> c; a = Hash (a), b = Hash (b); if (c == 1 ) e.push_back ({a, b}); else ue.push_back ({a, b}); } for (int i = 1 ; i <= idx; i++) p[i] = i; for (auto [x, y] : e) p[find (x)] = find (y); for (auto [x, y] : ue) if (find (x) == find (y)) { flag = false ; break ; } cout << (flag ? "YES" : "NO" ) << '\n' ; } return 0 ; }
奇偶游戏
239. 奇偶游戏 -
AcWing题库
用sum[n]存储前n个数的和,那么\(S[l\sim
r]\) 有奇数个1\(\Leftrightarrow\)
\(sum[l-1]\) 和\(sum[r]\) 奇偶性不同;\(S[l\sim r]\) 有偶数个1\(\Leftrightarrow\) \(sum[l-1]\) 和\(sum[r]\) 奇偶性相同
因为依次递推不止两种情况,所以用距离表示奇偶关系,\(d[x]=0\) 表示和根节点奇偶性相同,\(d[x]=1\) 表示和根节点奇偶性不同
使用异或^更新\(d[x]\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include <bits/stdc++.h> using namespace std;const int N = 1e4 + 10 ;int p[N], d[N];unordered_map<int , int > H; int n, m, idx;int Hash (int x) { if (!H.count (x)) H[x] = ++idx; return H[x]; } int find (int x) { if (x != p[x]) { int root = find (p[x]); d[x] ^= d[p[x]]; p[x] = root; } return p[x]; } int main () { cin >> n >> m; for (int i = 0 ; i < N; i++) p[i] = i; for (int i = 1 ; i <= m; i++) { int a, b; string c; cin >> a >> b >> c; a = Hash (a - 1 ), b = Hash (b); int t = 0 ; if (c[0 ] == 'o' ) t = 1 ; int pa = find (a), pb = find (b); if (pa == pb) { if (d[a] ^ d[b] != t) { cout << i - 1 ; return 0 ; } } else { p[pa] = pb; d[pa] = d[b] ^ d[a] ^ t; } } cout << m; return 0 ; }