并查集

并查集模板

 

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值