POJ 1984 Navigation Nightmare(二维带权并查集)

题目链接:http://poj.org/problem?id=1984

题目大意:有n个点,在平面上位于坐标点上,给出m关系F1  F2  L  D ,表示点F1往D方向走L距离到点F2,然后给出一系列询问F1   F2  I,表示在第I个关系给出后询问F1和F2两点间的曼哈顿距离,或者未知则输出-1。

解题思路:带权并查集,但是要开二维,val[][0]表示上下(南北)方向的偏移量,val[][1]表示左右(东西)方向的偏移量,然后一直更新就好,记得两个维度都要一起更新。

代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=5e4+5;
 8 int root[N],val[N][2],res[N];//val[][]用来记录权值,val[][0]表示南北方向的偏移量,val[][1]表示东西方向的偏移量 
 9 
10 struct node{
11     int a,b,len;
12     char det[5];
13 }arr[N];
14 
15 struct Node{
16     int a,b,id;
17     Node(){}
18     Node(int l,int r,int c){
19         a=l;
20         b=r;
21         id=c;
22     }
23 };
24 vector<Node>v[N];
25 
26 int find(int x){
27     if(root[x]==x)
28         return x;
29     int tmp=find(root[x]);
30     val[x][0]+=val[root[x]][0];
31     val[x][1]+=val[root[x]][1];
32     return root[x]=tmp;
33 }
34 
35 int main(){
36     int n,m;
37     scanf("%d%d",&n,&m);
38     for(int i=1;i<=n;i++){
39         root[i]=i;
40     }
41     for(int i=1;i<=m;i++){
42         scanf("%d%d%d%s",&arr[i].a,&arr[i].b,&arr[i].len,arr[i].det);
43     }
44     int q;
45     scanf("%d",&q);
46     for(int i=1;i<=q;i++){
47         int a,b,num;
48         scanf("%d%d%d",&a,&b,&num);
49         v[num].push_back(Node(a,b,i));
50     }
51     
52     for(int i=1;i<=m;i++){
53         int a=arr[i].a,b=arr[i].b,len=arr[i].len;
54         int t1=find(a);
55         int t2=find(b);
56         if(t1!=t2){
57             root[t2]=t1;
58             if(arr[i].det[0]=='N'){
59                 val[t2][0]=val[a][0]-val[b][0]+len;//val[t2][0]+val[b][0]=val[a][0]+len即a点向北走len距离到b点 
60                 val[t2][1]=val[a][1]-val[b][1];//东西方向没有发生偏移 
61             }
62             if(arr[i].det[0]=='S'){
63                 val[t2][0]=val[a][0]-val[b][0]-len;//val[t2][0]+val[b][0]=val[a][0]+len即a点向南走len距离到b点 
64                 val[t2][1]=val[a][1]-val[b][1];
65             }
66             if(arr[i].det[0]=='W'){
67                 val[t2][1]=val[a][1]-val[b][1]-len;//同理 
68                 val[t2][0]=val[a][0]-val[b][0];
69             }
70             if(arr[i].det[0]=='E'){
71                 val[t2][1]=val[a][1]-val[b][1]+len;
72                 val[t2][0]=val[a][0]-val[b][0];
73             }            
74         }
75         for(int j=0;j<v[i].size();j++){
76             a=v[i][j].a;
77             b=v[i][j].b;
78             t1=find(a);
79             t2=find(b);
80             if(t1!=t2)//两点不在同一个并查集中则两点间没有通路 
81                 res[v[i][j].id]=-1;
82             else 
83                 res[v[i][j].id]=abs(val[a][0]-val[b][0])+abs(val[a][1]-val[b][1]);
84         }
85     }
86     for(int i=1;i<=q;i++){            
87         printf("%d
",res[i]);
88     }
89     return 0;
90 }
原文地址:https://www.cnblogs.com/fu3638/p/7664041.html