5.6刷题并查集
P1551 亲戚
#include<bits/stdc++.h>
using namespace std;
const int N = 5010;
int f[N];
int find(int x){if(f[x] == x)return x;return f[x] = find(f[x]);
}
void solve(){int n, m, p; cin >> n >> m >> p;for(int i = 1; i <= n; i++)f[i] = i;for(int i = 0; i < m; i++){int x, y; cin >> x >> y;if(find(x) != find(y))f[find(x)] = find(y);}while(p--){int x, y; cin >> x >> y;if(find(x) == find(y))cout << "Yes" << endl;else cout << "No" << endl; }
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
P2024 [NOI2001] 食物链
#include<bits/stdc++.h>
using namespace std;
const int N = 50010;
int f[N], d[N];
int find(int x){if(f[x] != x){int t= f[x];f[x] = find(f[x]);d[x] = (d[t] + d[x] ) % 3;return f[x];}return x;
}
void solve(){int n, k; cin >> n >> k;for(int i = 1; i <= n; i++)f[i] = i;int s = 0;for(int i = 1; i <= k; i++){int type, x, y; cin >> type >> x >> y;if(type == 2 && x == y)s++;else if(x > n || y > n)s++;else{int pa = find(x);int pb = find(y); if(type == 1){if(pa != pb){f[pb] = pa;d[pb] = (3 + d[x] - d[y]) % 3;}else if(pa == pb && d[x] != d[y])s++;}else{if(pa != pb){f[pb] = pa;d[pb] = (3 + d[x] - d[y] + 1) % 3;}else if(pa == pb && (d[y] - d[x] + 3) % 3 != 1)s++;}}}cout << s << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
P1525 [NOIP 2010 提高组] 关押罪犯
做法1:带权值的并查集
#include<bits/stdc++.h>
using namespace std;
int f[20010], d[20010];
struct node{int x, y, c;
};
bool cmp(node a, node b){return a.c > b.c;
}
int find(int x){if(f[x] == x)return x;int t = f[x];f[x] = find(f[x]);d[x] = (d[t] + d[x]) % 2; return f[x];
}
void solve(){int n, k; cin >> n >> k;node b[100010];for(int i = 1; i <= n; i++)f[i] = i;for(int i = 0; i < k ; i++)cin >> b[i].x >> b[i].y >> b[i].c;sort(b, b + k, cmp);for(int i = 0; i < k; i++){int pa = find(b[i].x);int pb = find(b[i].y);if(pa != pb){f[pb] = pa;d[pb] = (2 + d[b[i].x] - d[b[i].y] + 1) % 2;}else if(pa == pb && d[b[i].x] == d[b[i].y]){cout << b[i].c;return;}}cout << 0 << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve(); return 0;
}
做法2:种类并查集,反集
#include<bits/stdc++.h>
using namespace std;
int f[40010];
struct node{int a, b, c;
}x[100010];
bool cmp(node a, node b){return a.c > b.c;
}
int find(int x){if(f[x] == x)return x;return f[x] = find(f[x]);
}
void solve(){int n, m; cin >> n >> m;for(int i = 1; i <= n; i++){f[i] = i;f[i + n] = i + n;}for(int i = 1; i <= m; i++){cin >> x[i].a >> x[i].b >> x[i].c;}sort(x + 1, x + m + 1, cmp);int ans = 0;for(int i = 1; i <= m; i++){int fa = find(x[i].a);int ffa = find(x[i].a + n);int fb = find(x[i].b);int ffb = find(x[i].b + n);if(fa == fb || ffa == ffb){ans = x[i].c;break;}else{f[fa] = ffb;f[fb] = ffa;}}cout << ans << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve(); return 0;
}
P1892 [BalticOI 2003] 团伙
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int f[N * 2];
int find(int x){if(f[x] == x)return x;return f[x] = find(f[x]);
}
void solve(){int n, m; cin >> n >> m;for(int i = 1; i <= n; i++){f[i] = i;f[i + n] = i + n;}while(m--){char type;int a, b;cin >> type >> a >> b;if(type == 'F'){f[find(a)] = find(b);}else{f[find(a + n)] = find(b);f[find(b + n)] = find(a);}}int sum = 0;for(int i = 1; i <= n; i++){if(f[i] == i)sum++;}cout << sum << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve(); return 0;
}
P1955 [NOI2015] 程序自动分析
注意范围是10^6不是题目中的10^5
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
int f[N];
struct node{int x, y;
}na[N], nb[N];
int find(int x){if(f[x] == x)return x;return f[x] = find(f[x]);
}
void solve(){int t; cin >> t;while(t--){int n; cin >> n;map<int, int> mp;int cnt = 1;int ia = 0, ib = 0;int flag = 0;for(int i = 1; i <= N; i++)f[i] = i;for(int i = 1; i <= n; i++){int x, y, type; cin >> x >> y >> type;if(mp.count(x) == 0)mp[x] = cnt++;if(mp.count(y) == 0)mp[y] = cnt++;if(type == 1){na[ia].x = x; na[ia++].y = y;}else{nb[ib].x = x; nb[ib++].y = y;}}for(int i = 0; i < ia; i++){int pa = find(mp[na[i].x]);int pb = find(mp[na[i].y]);if(pa != pb)f[pb] = pa;}for(int i = 0; i < ib; i++){int pa = find(mp[nb[i].x]);int pb = find(mp[nb[i].y]);if(pa == pb){flag = 1;break;}}if(flag)cout << "NO" << endl;else cout << "YES" << endl;}
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve(); return 0;
}
P1621 集合
暴力做法
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int f[N];
int gcd(int a, int b){if(b == 0)return a;return gcd(b, a % b);
}
int find(int x){if(x == f[x])return x;return f[x] = find(f[x]);
}
void solve(){int a, b, p; cin >> a >> b >> p;bool t[50001] = {};vector<int> z;for(int i = 2; i <= b / 2; i++){if(t[i] == 0){if(i >= p)z.push_back(i);for(int j = i + i; j <= b / 2; j += i)t[j] = 1;}}for(int i = a; i <= b; i++)f[i] = i;for(int i = 0; i < z.size(); i++){int s = 0;for(int j = a; j <= b; j++){if(j % z[i])continue;if(s == 0)s = find(j);else f[find(j)] = s;}}set<int> sc; for(int i = a; i <= b; i++){sc.insert(find(i));}cout << sc.size() << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
AC代码:找质数用并查集的路径压缩到一个父节点中,然后去重
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int f[N];
int find(int x){if(x == f[x])return x;return f[x] = find(f[x]);
}
void solve(){int a, b, p; cin >> a >> b >> p;bool t[N] = {};for(int i = 1; i <= b; i++)f[i] = i;for(int i = 2; i <= b; i++){if(t[i] == 0){for(int j = i + i; j <= b; j += i){t[j] = 1;if(i >= p){int pa = find(j);f[pa] = i;}}}}set<int> count;for(int i = a; i <= b; i++){count.insert(find(i));} cout << count.size() << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}