您的位置:首页 > 其它

并查集应用食物链poj1182

2015-07-26 16:19 253 查看
由于N,K大需要高效的维护动物之间的关系

快速判断是否产生矛盾

对于每只动物创建3个元素i-A,i-B,i-C,

并用这3*N个元素建立并查集

!!!!!

并查集里的每一个组表示组内所有元素代表的情况都同时发生或不发生

!!!!!

第一种,x和y属于同一种类,合并x-A和y-A,x-B,y-B,x-C和y-C

第二种,x吃y。。。。。。。。。合并x-a和y-b, x-b和y-c, x-c和y-a

在合并前要注意矛盾的情况:第一种,x和y要必须是属于同一类的,所以要排除A,b和A,C的情况

第二种,x不许满足A,B

#include<cstdio>
using namespace std;
#define MAX_K 150000
int N,K;
int T[MAX_K],X[MAX_K],Y[MAX_K];
int par[MAX_K*3];
int rankk[MAX_K*3];
void init(int n)
{
    for(int i=0;i<=n;i++){
        par[i]=i;
        rankk[i]=0;
    }
}
int find2(int x)
{
    if(par[x] == x) return x;
    else return par[x]=find2(par[x]);
}
void unite(int x,int y)
{
    x=find2(x);
    y=find2(y);
    if(x==y) return ;
    if(rankk[x] <rankk[y]) {
        par[x]=y;
    }else
    {
        par[y]=x;
        if(rankk[x]==rankk[y]) rankk[x]++;
    }
}
bool same(int x,int y)

{
    return find2(x) == find2(y);
}
void solve()
{
    //element x, x+N, x+2*N deputy x-A,x-B,x-C
    init(N * 3);
    int ans=0;
    for(int i=0;i<K;i++)
    {
        int t=T[i];
        int x=X[i]-1,y=Y[i]-1;
        if(x <0 || N<=x || y<0 || N<=y)
        {
            ans++;
            continue;
        }
        if(t == 1)
        {
            if(same(x,y+N) || same(x,y+2*N)) ans++;
            else
            {
                unite(x,y);
                unite(x+N,y+N);
                unite(x+N*2,y+N*2);
            }
        }
        else
        {
            if(same(x,y) || same(x,y+2*N)){
                ans++;
            }
            else {
                unite(x, y + N);
                unite(x+N, y+2*N);
                unite(x+2*N,y);
            }
        }
    }
    printf("%d\n",ans);
}
int main()
{
    scanf("%d%d",&N,&K);
    for(int i=0;i<K;i++)
        scanf("%d%d%d",&T[i],&X[i],&Y[i]);
    solve();
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: