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 ;}
#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 ;}