http://poj.org/problem?id=1984

    题目描述的如此蛋疼。。。

    关系并查集,用cx和cy数组记录点与根结点的相对位置,然后根据输入依次合并,当碰到询问时便计算距离,若不在同一集合中,即无法确定相对位置。

code:

#include<cstdio>
#include<cstring>
int p[40001], cx[40001], cy[40001] ;
int f1[10001], f2[10001], fi[10001] ;
struct edge{
    int s, e, l ;
    char d ;
}q[40001] ;
int abs(int a){
    return a>0?a:-a ;
}
void make_set(int n){
    for(int i=0; i<=n+1; i++){
        p[i] = i ;
        cx[i] = cy[i] = 0 ;
    }
}
int find_set(int x){
    int temp ;
    if(x!=p[x]){
        temp = p[x] ;
        p[x] = find_set(p[x]) ;
        cx[x] = cx[temp] + cx[x] ;
        cy[x] = cy[temp] + cy[x] ;
    }
    return p[x] ;
}
void union_set(int x){
    int a = q[x].s ;
    int b = q[x].e ;
    int pa = find_set(a) ;
    int pb = find_set(b) ;
    p[pb] = pa ;
    cx[pb] = cx[a] - cx[b] ;
    cy[pb] = cy[a] - cy[b] ;
    switch(q[x].d){
        case 'E':cx[pb] += q[x].l ;break ;
        case 'W':cx[pb] -= q[x].l ;break ;
        case 'N':cy[pb] += q[x].l ;break ;
        case 'S':cy[pb] -= q[x].l ;break ;
    }
    return ;
}
int main(){
    int n, m, k, i, j, t, x, y, z, tx, ty ;
    while(~scanf("%d%d", &n, &m)){
        make_set(n) ;
        for(i=1; i<=m; i++)
            scanf("%d %d %d %c", &q[i].s, &q[i].e, &q[i].l, &q[i].d) ;
        scanf("%d", &t) ;
        for(i=0; i<t; i++)
            scanf("%d%d%d", &f1[i], &f2[i], &fi[i]) ;
        int temp = 0 ;
        for(i=1; i<=m; i++){
            tx = find_set(q[i].s) ;
            ty = find_set(q[i].e) ;
            if(tx!=ty)
                union_set(i) ;
            while(fi[temp]==i){
                tx = find_set(f1[temp]) ;
                ty = find_set(f2[temp]) ;
                if(tx!=ty)  printf("-1\n") ;
                else{
                    tx = abs(cx[f1[temp]] - cx[f2[temp]]) ;
                    ty = abs(cy[f1[temp]] - cy[f2[temp]]) ;
                    printf("%d\n", tx + ty) ;
                }
                temp ++ ;
            }
        }
    }
    return 0 ;}

 

posted on 2012-04-21 21:15  追逐.  阅读(265)  评论(1编辑  收藏  举报