模板

并查集

const int maxn=100010;
int f[maxn];

void init(){
	for(int i=1;i<=n;i++) f[i]=i;
} 

int find(int x){
	if(x==f[x]) return x;
	return f[x]=find(f[x]);
}

void join(int x,int y){
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy) f[fx]=fy;
}

种类并查集
种类并查集维护一种循环对称的关系,通常要有多个集合
带权并查集
带权并查集维护多个元素之间的连通关系以及偏移关系,偏移可以为当前节点到根节点的边长之和

const int maxn=200010,maxm=40010;
int f[maxn],sum[maxn];

void init(){
    for(int i=1;i<=n;i++){
        f[i]=i;
        sum[i]=0;
    }
}

int find(int x){
    if(f[x]!=x){
        int t=f[x];
        f[x]=find(f[x]);
        sum[x]+=sum[t];
    }
    return f[x];
}

void join(int x,int y,int s){
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy){
        f[fx]=fy;
        sum[fx]=-sum[x]+s+sum[y];
    }
}

模板题:hdu3038 How Many Answers Are Wrong

#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;

const int maxn=200010,maxm=40010;
int n,m,f[maxn],sum[maxn];

void init(){
    for(int i=0;i<=n;i++){
        f[i]=i;
        sum[i]=0;
    }
}

int find(int x){
    if(f[x]!=x){
        int t=f[x];
        f[x]=find(f[x]);
        sum[x]+=sum[t];
    }
    return f[x];
}

void join(int x,int y,int s){
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy){
        f[fx]=fy;
        sum[fx]=-sum[x]+s+sum[y];
    }
}

int main(){
    while(scanf("%d %d",&n,&m)!=EOF){
        init();
        int ans=0;
        for(int i=1;i<=m;i++){
            int a,b,s;
            scanf("%d %d %d",&a,&b,&s);
            a--;
            if(find(a)==find(b)){
                if(sum[a]-sum[b]!=s) ans++;
            }
            else{
                join(a,b,s);
            }
        }
        printf("%d\n",ans);
    }
} 
posted @ 2020-10-02 22:44  fxq1304  阅读(8)  评论(0编辑  收藏  举报