例题 格子游戏
思路
判断每画一条线,该图是否会形成环,可以利用并查集,判断该线段的两个端点是否属于同一个祖宗,是则形成环。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 205;
int n, m;
int p[N * N];
int res;
int gethash(int a, int b) {
return (a - 1) * n + b;
}
int find(int x) {
if (p[x] != x) {
return p[x] = find(p[x]);
}
else {
return x;
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n * n; ++i) {
p[i] = i;
}
while (m--) {
int a, b;
char c;
cin >> a >> b >> c;
int x = find(gethash(a, b));
int y;
if (c == 'D') {
y = find(gethash(a + 1, b));
}
else {
y = find(gethash(a, b + 1));
}
if (x != y) {
res++;
p[x] = y;
}
else {
cout << ++res;
return 0;
}
}
cout << "draw";
return 0;
}
例题 搭配购买
思路
利用并查集,将关联的云朵看成一个整体,再利用背包去做。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int p[N], wei[N], val[N], dp[N];
int n, m, w;
int find(int x) {
if (p[x] != x) {
return p[x] = find(p[x]);
}
return p[x];
}
int main() {
cin >> n >> m >> w;
for (int i = 1; i <= n; ++i) {
cin >> wei[i] >> val[i];
p[i] = i;
}
for (int i = 1; i <= m; ++i) {
int x, y;
cin >> x >> y;
int a = find(x), b = find(y);
if (a != b) {
p[a] = b;
wei[b] += wei[a];
val[b] += val[a];
}
}
for (int i = 1; i <= n; ++i) {
if (p[i] == i) {
for (int j = w; j >= wei[i]; --j) {
dp[j] = max(dp[j], dp[j - wei[i]] + val[i]);
}
}
}
cout << dp[w];
return 0;
}
例题程序自动分析
思路
将所有的相等关系放到一个容器A中,所有的不等关系放到另外一个容器B中。通过容器A更新并查集,最后通过容器B判断当前所有关系是否矛盾。
由于本题数据大,每一次solve(),可以给 i 和 j 对应的编号。
代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6 + 2000;
int cnt;
int n;
unordered_map<int, int> d;//存储某个数字对应的编号
vector<PII> uneq, eq;
int p[N];
int mapping(int x) {
if (d.count(x) == 0) {
return d[x] = cnt++;
}
return d[x];
}
int find(int x) {
if (p[x] != x) {
return p[x]=find(p[x]);
}
return p[x];
}
void solve() {
d.clear();
eq.clear();
uneq.clear();
cnt = 1;
cin >> n;
for (int i = 1; i <= n; ++i) {
int x, y, e;
cin >> x >> y >> e;
x = mapping(x), y = mapping(y);
if (e) {
eq.push_back({x, y});
}
else {
uneq.push_back({x, y});
}
}
for (int j = 1; j < cnt; ++j){
p[j] = j;
}
for (auto x : eq) {
p[find(x.first)] = find(x.second);
}
bool flag = true;
for (auto x : uneq) {
if (find(x.first) == find(x.second)) {
flag = false;
break;
}
}
cout << (flag ? "YES" : "NO") << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--){
solve();
}
return 0;
}