并查集应用食物链poj1182

来源:互联网 发布:上海兄弟连java学费 编辑:程序博客网 时间:2024/06/08 00:51

由于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 150000int 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;}


0 0
原创粉丝点击