poj1182 带权并查集

带权并查集

利用路径压缩之后,所有点到祖先距离为1,合并集合只需要更改某一祖先的权值,那么只要权值具有相对性,只需要在getfather步骤里从父节点递归获取权值即可

#include<cstdio>
#define rep(i,a,b) for (int i=a;i<=b;++i)
using namespace std;
int n,ans,a,x,y,q,w,k;
int fa[60000];
int dis[60000];



int getfather(int x)
{
    if (fa[x]==x) return x;
    int t=fa[x];
    fa[x]=getfather(t);
    dis[x]=(dis[x]+dis[t])%3;
    return fa[x];
}

void Union(int a,int b,int father,int son,int dist)
{
    dis[b]=(-dis[son]+dis[father]+dist+3)%3;
    fa[b]=a;
}

int main()
{
    scanf("%d%d",&n,&k);
    rep(i,1,n) fa[i]=i,dis[i]=0;
    ans=0;
    rep(i,1,k)
    {
        //printf("%d\n",ans);
        scanf("%d%d%d",&a,&x,&y);
        --a;
        if (x>n || y>n) {++ans;continue;}
        q=getfather(x);w=getfather(y);
        if (q==w){if (!((a==0 && dis[x]==dis[y]) || (a==1 && (dis[x]-dis[y]+1)%3==0))) ++ans;}
            else Union(q,w,x,y,a);
    }
    printf("%d\n",ans);
    return 0;
}

 

posted on 2017-07-22 13:31  心里只有学习  阅读(134)  评论(1编辑  收藏  举报

导航