POJ_1984_(带权并查集)

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 协议 ,转载请注明出处!