1023 ProblemW

题意:
有n个人坐在体育馆里面,然后给出m个他们之间的距离, A B X, 代表B的座位比A多X. 然后求出这m个关系之间有多少个错误,所谓错误就是当前这个关系与之前的有冲突。
思路:
首先这个体育馆无限大,可以忽略圆圈的情况
用带权并查集做, 对于并查集中的每一棵数, 树根的距离为0,然后以树根作为参照,每个结点的权值代表与树根的距离。把A树合并到B树上,这时要给A树的跟结点root_a赋值:rank[root_a] = rank[A]+x-rank[B]。

又一个很神奇的事情,我用CIN COUT做竟然语法错误用scanf做就没错。。。。在codeblocks上编译能过去,到了这就错了。。。

#include<cstdio>
#include<cmath>
using namespace std;
#define N 50005
int f[N], rank[N], n, m;

void init(){
    for(int i=0; i<=n; ++i)
        f[i]=i, rank[i]=0;
}
int find(int x){
    if(x==f[x]) return f[x];
    int t=f[x];
    f[x] = find(f[x]);
    rank[x] += rank[t];
    return f[x];
}
bool Union(int x,int y, int m){
    int a=find(x), b=find(y);
    if(a==b){
        if(rank[x]+m!=rank[y])
            return false;
        return true;
    }
    f[b] = a;
    rank[b] = rank[x]+m-rank[y];
    return true;
}

int main(){
    int a,b,x;
    while(~scanf("%d%d",&n,&m)){
        init();
        int cnt=0;
        for(int i=0; i<m; ++i){
            scanf("%d%d%d",&a,&b,&x);
            if(!Union(a, b, x)){
                ++cnt;
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/s7799653/article/details/51813819