并查集
并查集
板子
struct DSU{
int num;
vector<int> fa, sz;
DSU(int x) : num(x), fa(x + 1), sz(x + 1, 1){
for(int i = 0; i <= x; ++ i){
fa[i] = i;
}
}
int size(int x){ return sz[findfa(x)]; }
int findfa(int x){
while(x != fa[x]) x = fa[x] = fa[fa[x]];
return x;
}
bool same(int x, int y){ return findfa(x) == findfa(y); }
bool merge(int x, int y){
x = findfa(x); y = findfa(y);
if(x == y) return false;
sz[x] += sz[y];
fa[y] = x;
return true;
}
};
相关资料
oi wiki - dsu
并查集 --算法竞赛专题解析(3)
例题
2023ACM暑假训练day 2 并查集
带权并查集
我们可以在并查集的边上定义某种权值、以及这种权值在路径压缩时产生的运算,从而解决更多的问题
例题2道
1.hdu 3038 How Many Answers Are Wrong
利用带权并查集解决这个问题则非常简单
具体思想非常值得理解!!!
//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
#define debug(x) cout << #x << " = " << x << endl
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << endl
//#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ull,ull> pull;
typedef pair<double,double> pdd;
/*
带权并查集
*/
const int maxm=2e5+5,inf=0x3f3f3f3f,mod=998244353;
int n,m,fa[maxm],d[maxm],ans;
int findfa(int x){
if(fa[x]!=x){
int t=fa[x];//记下原父节点,等会更新
fa[x]=findfa(fa[x]);
d[x]+=d[t];//更新从节点x到根的距离
}
return fa[x];
}
void merge(int a,int b,int c){
int x=findfa(a),y=findfa(b);
if(x==y){
if(d[a]-d[b]!=c) ++ans;//区间差不为c时说明当前给定的数据是假的
}else{
fa[x]=y;
d[x]=d[b]+c-d[a];//此处更新的是d[x],不是d[b]。因为x不作为终点了
}
return ;
}
void pre(int x){
for(int i=0;i<=n;++i){
fa[i]=i;
d[i]=0;
}
ans=0;
return ;
}
void solve(){
while(cin>>n>>m){
pre(n);
int a,b,c;
for(int i=0;i<m;++i){
cin>>a>>b>>c;
--a;
merge(a,b,c);
}
cout<<ans<<'\n';
}
return ;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _=1;
// cin>>_;
while(_--){
solve();
}
return 0;
}
2.poj 1182 食物链
具体思路见中间罗老师的链接
本题的权值不是简单的相加
关键两点就是路径压缩时,怎么改变权值;合并时,怎么改变权值;如何判断矛盾。
这就是本题的三个关键之处
//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
#define debug(x) cout << #x << " = " << x << endl
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << endl
//#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ull,ull> pull;
typedef pair<double,double> pdd;
/*
*/
const int maxm=5e4+5,inf=0x3f3f3f3f,mod=998244353;
int n,k,ans,fa[maxm],d[maxm];
void pre(){
ans=0;
for(int i=0;i<=n;++i) fa[i]=i;
return ;
}
int findfa(int x){
if(x!=fa[x]){
int t=fa[x];
fa[x]=findfa(fa[x]);
d[x]=(d[x]+d[t])%3;
}
return fa[x];
}
void merge(int c,int a,int b){
int x=findfa(a),y=findfa(b);
if(x==y){
if(c - 1 != ((d[a] - d[b] + 3) % 3)) ++ans;
}else{
fa[x]=y;
d[x]=(d[b]-d[a]+c-1)%3;
}
return ;
}
void solve(){
cin>>n>>k;
pre();
int c,a,b;
for(int i=0;i<k;++i){
cin>>c>>a>>b;
if(a>n||b>n||c==2&&a==b) ++ans;
else merge(c,a,b);
}
cout<<ans<<'\n';
return ;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _=1;
// cin>>_;
while(_--){
solve();
}
return 0;
}
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17512808.html