并查集

来源:互联网 发布:java第三方支付 编辑:程序博客网 时间:2024/06/06 13:10

并查集模板

int finds(int x){    return fa[x]==x?x:fa[x]=finds(fa[x]);}bool bing(int x,int y){    int fx=finds(x);    int fy=finds(y);    if(fx==fy) return 0;    fa[fy]=fx;    return 1;}

经典:http://poj.org/problem?id=2236

#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>using namespace std;const int N=1e3+10;struct node{    int x,y;}f[N];int t,n,m,d;int fa[N],mp[N][N];bool vis[N];int calc(node x,node y){    return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);}int finds(int x){    return fa[x]==x?x:fa[x]=finds(fa[x]);}void bing(int x,int y){    x=finds(x);    y=finds(y);    if(x!=y) fa[x]=y;}int main(){    int x,y;    memset(mp,0,sizeof mp);    memset(vis,0,sizeof vis);    for(int i=0;i<N;i++) fa[i]=i;    scanf("%d%d",&n,&d);    for(int i=1;i<=n;i++)    {        scanf("%d%d",&f[i].x,&f[i].y);        for(int j=1;j<i;j++)            if(calc(f[i],f[j])<=d*d)                mp[i][j]=mp[j][i]=1;    }    char ch;    while(cin>>ch)    {        if(ch=='O')        {            scanf("%d",&x);            vis[x]=1;            for(int i=1;i<=n;i++)                if(i!=x&&mp[x][i]&&vis[i])  bing(x,i);        }        else        {            scanf("%d%d",&x,&y);            if(finds(x)==finds(y)) printf("SUCCESS\n");            else printf("FAIL\n");        }    }    return 0;}

种类并查集:http://poj.org/problem?id=1182




#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int N=200000+10;int fa[N],sum[N];int finds(int x){    if(fa[x]!=x)    {        int y=fa[x];        fa[x]=finds(fa[x]);        sum[x]+=sum[y];    }    return fa[x];}bool bing(int x,int y,int d){    int fx=finds(x);    int fy=finds(y);    if(fx==fy) return sum[y]!=sum[x]+d;    fa[fy]=fx;    sum[fy]=sum[x]-sum[y]+d;    return 0;}int main(){    int t,n,m,x,y,d,tt=0;    while(~scanf("%d%d",&n,&m))    {        for(int i=0;i<N;i++) fa[i]=i,sum[i]=0;        int ans=0;        while(m--)        {            scanf("%d%d%d",&x,&y,&d);            if(bing(x-1,y,d)) ans++;        }        printf("%d\n",ans);    }    return 0;}
带权并查集http://acm.hdu.edu.cn/showproblem.php?pid=3038


#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int N=200000+10;int fa[N],sum[N];int finds(int x){    if(fa[x]!=x)    {        int y=fa[x];        fa[x]=finds(fa[x]);        sum[x]+=sum[y];    }    return fa[x];}bool bing(int x,int y,int d){    int fx=finds(x);    int fy=finds(y);    if(fx==fy) return sum[y]!=sum[x]+d;    fa[fy]=fx;    sum[fy]=sum[x]-sum[y]+d;    return 0;}int main(){    int t,n,m,x,y,d,tt=0;    while(~scanf("%d%d",&n,&m))    {        for(int i=0;i<N;i++) fa[i]=i,sum[i]=0;        int ans=0;        while(m--)        {            scanf("%d%d%d",&x,&y,&d);            if(bing(x-1,y,d)) ans++;        }        printf("%d\n",ans);    }    return 0;}

逆向并查集http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261


#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<cstdio>#include<cmath>#include<map>using namespace std;const int N=10010;int pre[N+10];int sum[N+10];//最大值int val[N+10];//下标int a[N+10];int ans[N*10];struct node{    int x,y;};node num[N*10];node destory[N*10];map<int,int>mp[N];int use[N*2];void init(){    for(int i=0;i<N;i++)        pre[i]=i;    memset(use,0,sizeof use);}int Find(int x){    if(pre[x]!=x)        pre[x]=Find(pre[x]);    return pre[x];}int Union(int x,int y){    int fx=Find(x);    int fy=Find(y);    if(fx!=fy)    {        pre[fx]=fy;        if(sum[fx]>sum[fy])        {            sum[fy]=sum[fx];            val[fy]=val[fx];//下标        }else if(sum[fx]==sum[fy] && val[fy]>val[fx])            val[fy]=val[fx];    }}int main(){    int n,m;    int i,j,k;    int x,y,w,t;    int cnt,q;    char str[20];    t=0;    while(~scanf("%d",&n))    {        if(t==1) puts("");        else t=1;        init();        for(i=0;i<n;i++)        {            scanf("%d",&a[i]);            mp[i].clear();            sum[i]=a[i];            val[i]=i;        }        scanf("%d",&m);        for(i=0;i<m;i++)         {              scanf("%d%d",&x,&y);              if(x>y) swap(x,y);              num[i].x=x;              num[i].y=y;              mp[x][y]=i;         }        scanf("%d",&q);        for(j=0;j<q;j++)        {            scanf("%s",str);            if(str[0]=='q')            {                scanf("%d",&x);                destory[j].x=x;                destory[j].y=-1;            }else{                scanf("%d%d",&x,&y);                if(x>y)swap(x,y);                int tmp=mp[x][y];                use[tmp]=1;                destory[j].x=x;                destory[j].y=y;            }        }        for(i=0;i<m;i++)            if(!use[i])                Union(num[i].x,num[i].y);        cnt=0;        for(i=q-1;i>=0;i--)        {            if(destory[i].y==-1)            {                x=destory[i].x;                int t1=Find(x);                if(sum[t1]>a[x]) ans[cnt++]=val[t1];                else ans[cnt++]=-1;            }else{                Union(destory[i].x,destory[i].y);            }        }        for(i=cnt-1;i>=0;i--)            printf("%d\n",ans[i]);    }    return 0;}

枚举+并查集 http://poj.org/problem?id=2912

/*POJ 2912枚举+并查集枚举每一个裁判,看有没有不出错的如果没有,说明是Impossible如果有超过一个,那么就是Can not determine如果只有一个,那么输出其他出错的位置的最大值*/#include <stdio.h>#include <string.h>#include <algorithm>#include <iostream>using namespace std;const int MAXN=510;const int MAXM=2010;struct Node{    int u,v;    int re;}node[MAXM];int F[MAXN];int val[MAXN];int find(int x){    if(F[x]==-1)return x;    int tmp=find(F[x]);    val[x]+=val[F[x]];    val[x]%=3;    return F[x]=tmp;}char str[30];int main(){    int n,m;    int u,v;    while(scanf("%d%d",&n,&m)==2)    {        gets(str);        for(int i=0;i<m;i++)        {            //scanf("%s",&str);            gets(str);            int t=0;            int len=strlen(str);            for(t=0;t<len;t++)              if(str[t]=='>'||str[t]=='='||str[t]=='<')                break;            u=0;            for(int j=0;j<t;j++)            {                u*=10;                u+=str[j]-'0';            }            v=0;            for(int j=t+1;j<len;j++)            {                v*=10;                v+=str[j]-'0';            }            node[i].u=u;            node[i].v=v;            if(str[t]=='=')node[i].re=0;            else if(str[t]=='<')node[i].re=1;            else node[i].re=2;        }        int ansi;        int anst=0;        int t0=0;//不矛盾的个数        for(int i=0;i<n;i++)        {            memset(F,-1,sizeof(F));            memset(val,0,sizeof(val));            int ff=-1;            for(int j=0;j<m;j++)            {                if(node[j].u==i || node[j].v==i)continue;                u=node[j].u;                v=node[j].v;                int t1=find(u);                int t2=find(v);                if(t1==t2)                {                    if(val[v]!=(val[u]+node[j].re)%3)                    {                        ff=j+1;                        break;                    }                }                else                {                    F[t2]=t1;                    val[t2]=val[u]-val[v]+node[j].re;                    val[t2]=(val[t2]+3)%3;                }            }            if(ff==-1)            {                ansi=i;                t0++;            }            else anst=max(anst,ff);        }        if(t0==0)printf("Impossible\n");        else if(t0>=2)printf("Can not determine\n");        else           printf("Player %d can be determined to be the judge after %d lines\n",ansi,anst);    }    return 0;}


0 0