HDU 3047 Zjnu Stadium(带权并查集)

题意:有一个环形体育场,有n个人坐,给出m个位置关系,A B x表示B所在的列在A的顺时针方向的第x个,在哪一行无所谓,因为假设行有无穷个。

  给出的座位安排中可能有与前面矛盾的,求有矛盾冲突的个数。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;
const int maxn=50010;
int n,m,r;
int father[maxn];
int pos[maxn];//pos[i]表示i相对根节点的位置(始终大于0的,顺时针方向)

void init(){
    for(int i=1;i<=n;i++){
        father[i]=i;
        pos[i]=0;
    }
}
//查找父节点的时候,同步更新子节点相对更节点的位置
int find_root(int x){
    if(father[x]==x)
        return x;
    int fa=father[x];
    father[x]=find_root(father[x]);
    pos[x]=(pos[x]+pos[fa])%300;
    return father[x];
}


void Union(int fa,int fb){
    father[fb]=fa;
}
int main()
{
    int a,b,x;
    while(scanf("%d%d",&n,&m)!=EOF){
        r=0;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&x);
            int fa=find_root(a);
            int fb=find_root(b);
            if(fa!=fb){
                Union(fa,fb);
                /*
                b相对a的顺时针位置为x,b相对父节点fb的位置为pos[b],则fb相对b的位置为-pos[b],
                a相对父节点fa的位置为pos[a]。
                fb相对a的位置为-pos[b]+x,fb相对fa的位置即为(-pos[b]+a+pos[a],
                这里为防止出现负数,加了300
                */
                pos[fb]=(x-pos[b]+pos[a]+300)%300;
            }
            else{
                /*
                b相对于a的位置
                设a、b的根节点为f,则相对a的位置为-pos[a],b相对f的位置为pos[b],
                则b相对a的位置为(-pos[a]+pos[b]),这里同样为防止出现负数,加了300
                */
                int t=(-pos[a]+pos[b]+300)%300;
                if(t!=x){
                    r++;
                }
            }
        }
        printf("%d
",r);
    }
    return 0;
}


  

原文地址:https://www.cnblogs.com/chenxiwenruo/p/3296630.html