POJ_1984_(带权并查集)
自己审题问题极其严重
1.忽略了该题询问i行
可能询问多次,
2.忽略了给出询问行不是按顺序的排序的,我以为是按顺序,
- 没有想出怎么用带权并查集做
- 根据给出的东南西北来维护
dx
横坐标到根节点距离dy
纵坐标到根节点距离, - 路径压缩的时候
dx
dy
一起压缩就行,主要是合并的时候根据题目给出的东南西北来确定dx
dy
- 合并根节点 还是
rala[ra] = rala[b] + s - rala[a]
,本质的东西没有变(还是矢量 相加减)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130#include <iostream>
#include <queue>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn = 4e4+10;
int pre[maxn];
long long dx[maxn];
long long dy[maxn];
struct point {
int time;
int u,v;
point () {
}
point (int a,int b,int c) {
u = a;
v = b;
time = c;
}
bool operator< (const point& t) const {
return time < t.time;
}
} p[maxn];
struct node {
int u,v;
int dist;
char dir;
node () {
}
node (int a,int b,int d,char c) {
u = a;
v = b;
dist = d;
dir = c;
}
}e[maxn];
int n,m,k;
void init() {
memset(dx,0,sizeof dx);
memset(dy,0,sizeof dy);
for (int i=1; i<=n; i++) pre[i] = i;
}
int find(int x) {
int temp = pre[x];
if (pre[x] == x) return x;
pre[x] = find(pre[x]);
dx[x] += dx[temp];
dy[x] += dy[temp];
return pre[x];
}
void merge(int i) {
int a = e[i].u;
int b = e[i].v;
int ra = find(a);
int rb = find(b);
if (ra != rb) {
int tx=0,ty=0;
if (e[i].dir == 'E') tx = e[i].dist;
else if (e[i].dir == 'W') tx = -e[i].dist;
else if (e[i].dir == 'S') ty = -e[i].dist;
else if (e[i].dir == 'N') ty = e[i].dist;
pre[ra] = rb;
dx[ra] = dx[b] - dx[a] + tx;
dy[ra] = dy[b] - dy[a] + ty;
}
}
int main() {
// freopen("a.txt","r",stdin);
cin >> n >> m;
for (int i=1; i<=m; i++) {
int a,b,d;
char ch;
cin >> a >> b >> d >> ch;
node t(a,b,d,ch);
e[i] = t;
}
cin >> k;
for (int i=1; i<=k; i++) {
int a,b,c;
cin >> a >> b >> c;
point t(a,b,c);
p[i] = t;
}
sort(p+1,p+1+k);
int time;
int u,v;
int cnt = 2;
u = p[1].u;
v = p[1].v;
time = p[1].time;
init();
for (int i=1; i<=m; i++) {
//建图
merge(i);
while (time == i) { //忽略了 第i个可能会被问到多次的情况
int ra = find(u);
int rb = find(v);
if (ra == rb) {
printf("%d\n",abs(dx[u]-dx[v])+abs(dy[u]-dy[v]) );
}
else {
printf("-1\n");
}
u = p[cnt].u;
v = p[cnt].v;
time = p[cnt].time;
cnt++;
if (cnt > k+1) break;
}
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!