最近做了好多并查集的题目,整理了一下放在一起
CF859E Desk Disorder
链接
判环和子环,算方案数
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+100;
int faz[maxn],size[maxn],loop[maxn],circle[maxn];
int find(int x){
if (x == faz[x]) return x;
else return faz[x] = find(faz[x]);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
for (int i=1;i<=2*n;i++)
faz[i] = i,size[i] = 1;
for (int i=1;i<=n;i++){
int x,y;
cin >> x >> y;
if (x == y) loop[x] = 1;
int fx = find(x),fy = find(y);
if (fx != fy){
faz[fx] = faz[fy];
loop[fy] |= loop[fx];
size[fy] += size[fx];
size[fx] = 0;
}
else circle[fx] =1;
}
long long ans = 1;
for (int i=1;i<=2*n;i++){
if (find(i) == i && loop[i] == 0){
if (circle[i] != 0)
ans<<=1;
else ans*=size[i];
}
ans %=1000000007;
}
cout << ans;
return 0;
}
CF1209D Cow and Snacks
题意
n 种花,k 个客人,每个人喜欢两种编号不同的花。但是每种花在花店里只有一束。
客人按顺序进入花店,会买走所有她喜欢且仍在店铺里的花。如果一个客人买不到任何一束花,那么她就会十分沮丧导致变成肥宅。现在你可以自己安排这 n 个人的顺序,使得肥宅的数量最小。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int v[maxn];
void init(int n)
{
for(int i=0; i<=n; i++)
v[i]=i;
}
int finds(int x)
{
if(x==v[x]) return x;
return v[x]=finds(v[x]);
}
bool unite(int x,int y)
{
x=finds(x);
y=finds(y);
if(x!=y)
{
v[x]=y;
return true;
}
return false;
}//
int main()
{
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n,k,x,y,ans=0;
cin >> n >> k;
init(n);
for(int i=0; i<k; i++)
{
cin >> x >> y;
if(!unite(x,y)) ans++;
}
cout << ans << endl;
return 0;
}
带权并查集
//路径压缩
int find(int x) {
if (x != faz[x]) {
int t = faz[x];
faz[x] = find(faz[x]);
sum[x] += sum[t];
}
return faz[x];
}
//合并
int px = find(x);
int py = find(y);
if (px != py){
parent[px] = py;
value[px] = -value[x] + value[y] + s;
}
HDU-3038-How Many Answers Are Wrong
链接
有M个数,不知道它们具体的值,但是知道某两个数之间(包括这两个数)的所有数之和,现在给出N个这样的区间和信息,需要判断有多少个这样的区间和与前边已知的区间和存在矛盾。
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 2e5 + 100;
int faz[maxn], sum[maxn];
int find(int x) {
if (x != faz[x]) {
int t = faz[x];
faz[x] = find(faz[x]);
sum[x] += sum[t];
}
return faz[x];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int m, n;
while (cin >> n >> m) {
for (int i = 0; i <= n; i++) {
faz[i] = i;
sum[i] = 0;
}
int ans = 0;
for (int i = 1; i <= m; i++) {
int l, r, val;
cin >> l >> r >> val;
l--;//左开右闭所以往左边挪一个
int fl = find(l), fr = find(r);
if (fl == fr) {
if (sum[l] - sum[r] != val) ans++;
} else {
faz[fl] = fr;
sum[fl] = -sum[l] + sum[r] + val;
}
}
cout << ans << endl;
}
return 0;
}