HDU 3047 Zjnu Stadium 带权并查集

Z Zjnu Stadi

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4182 Accepted Submission(s): 1600

Problem Description

In 12th Zhejiang College Students Games 2007, there was a new stadium built in Zhejiang Normal University. It was a modern stadium which could hold thousands of people. The audience Seats made a circle. The total number of columns were 300 numbered 1–300, counted clockwise, we assume the number of rows were infinite.
These days, Busoniya want to hold a large-scale theatrical performance in this stadium. There will be N people go there numbered 1–N. Busoniya has Reserved several seats. To make it funny, he makes M requests for these seats: A B X, which means people numbered B must seat clockwise X distance from people numbered A. For example: A is in column 4th and X is 2, then B must in column 6th (6=4+2).
Now your task is to judge weather the request is correct or not. The rule of your judgement is easy: when a new request has conflicts against the foregoing ones then we define it as incorrect, otherwise it is correct. Please find out all the incorrect requests and count them as R.

Input

There are many test cases:
For every case:
The first line has two integer N(1<=N<=50,000), M(0<=M<=100,000),separated by a space.
Then M lines follow, each line has 3 integer A(1<=A<=N), B(1<=B<=N), X(0<=X<300) (A!=B), separated by a space.

Output

For every case:
Output R, represents the number of incorrect request.

Sample Input

10 10
1 2 150
3 4 200
1 5 270
2 6 200
6 5 80
4 7 150
8 9 100
4 8 50
1 7 100
9 2 100

Sample Output

2

Hint:
(PS: the 5th and 10th requests are incorrect)

Source

2009 Multi-University Training Contest 14 - Host by ZJNU

题意:
有n个人坐成一排,每次给出两个人的关系A,B,X,表示B在A的右侧X的位置处,求给出的关系中有多少不合法的。
多组数据。

分析:
因为人与人之间的关系具有传递性,不难想到带权并查集。
对于每组给出的A,B,X:
(1)如果A、B之前没有关系(不在同一个联通块中),那么这个肯定合法,并将它们连接起来。连接时即将
B的祖先接在A的祖先上,B在rtB右侧rk[B]处,而B在A右侧d处,A在rtA右侧rk[A]处,
所以不难得出B在rtA右侧d+rk[A]处,则rtB在rtA右侧rk[A]+d-rk[B]处。

(2)如果A和B在同一个联通块内,就只需要判断它们之间的距离与给出的d是否一致即可。A在rt右侧rk[A]处,B在rt右侧rk[B]处,则根据之前的联通关系:B在A右侧rk[B]-rk[A]处,再判断是否合法即可。

路径压缩的时候也很好处理,rk[x]+=rk[fa[x]];

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 50000 + 10;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

inline int Abs(int x) {return x<0?(-x):x;}

int n,m;
int fa[N],rk[N];
int ans=0;

int find(int x){
    if(x==fa[x]) return fa[x];
    int d=find(fa[x]);
    rk[x]+=rk[fa[x]];
    return fa[x]=d;
}

int getans(int x,int y,int d){
    int fx=find(x),fy=find(y);
    if(fx==fy){
    //  printf("ss%d %d %d\n",x,y,Abs(rk[x]-rk[y]));
        if(d!=-rk[x]+rk[y]) return 1;
        return 0;
    }
    fa[fy]=fx;
    rk[fy]=rk[x]-rk[y]+d;
    return 0;
}

void update(){
    ans=0;
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
       update();
       for(register int i=1;i<=n;i++) fa[i]=i,rk[i]=0;
       while(m--){
          int a=read(),b=read(),x=read();
          ans+=getans(a,b,x);
       //   for(register int i=1;i<=n;i++)
       //       printf("%d ",rk[i]);
       //   printf("\n");
       }
       printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值