POJ-1984-Navigation Nightmare [带权并查集]


题目传送门


题意:
按顺序给出两个节点之间的距离和方向,求在某一时刻两个点之间的曼哈顿距离。
思路:
因为需要求某个时刻的曼哈顿距离,所以要将所有的数据存起来离线操作。
规定向E为x+, 向南为y+,建立坐标系。
用带权并查集更新,并在更新过程中输出询问结果。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
struct node1{
    int f1, f2, x, y;
}P[40000+1000];
struct node2{
    int x,y,t,index;
}Q[10000+1000];
struct node3{
    int fa;
    int dx,dy;
}F[40000+1000];
int ans[40000+1000];
bool cmp(node2 a, node2 b)
{
    return a.t<b.t;
}
void init()
{
    for (int i = 1; i <= 40000; i++)
    {
        F[i].fa = i;
        F[i].dx = 0;
        F[i].dy = 0;
        ans[i] = 0;
    }
    return ;
}
int find(int x)
{
    if (x==F[x].fa) return x;
    int t = F[x].fa;
    F[x].fa = find(F[x].fa);
    F[x].dx += F[t].dx;
    F[x].dy += F[t].dy;
    return F[x].fa;
}
int main(void)
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    init();
    int n,m;
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        char ch[3];
        int p;
        scanf("%d %d %d %s", &P[i].f1, &P[i].f2, &p, ch);
        if (ch[0]=='W' || ch[0]=='E')
        {
            P[i].y = 0;
            P[i].x = ch[0]=='E' ? p:-p;
        }
        if (ch[0]=='S' || ch[0]=='N')
        {
            P[i].x = 0;
            P[i].y = ch[0]=='S'? p:-p;
        }
    }
    int k;
    scanf("%d", &k);
    for (int i = 0; i < k; i++)
    {
        scanf("%d %d %d", &Q[i].x, &Q[i].y, &Q[i].t);
        Q[i].index = i;
    }
    sort(Q,Q+k,cmp);
    int I = 0;
    for (int i = 0; i < m; i++)
    {
        int a = find(P[i].f1);
        int b = find(P[i].f2);
        if (a!=b)
        {
            F[a].fa = b;
            F[a].dx = F[P[i].f2].dx - F[P[i].f1].dx + P[i].x;
            F[a].dy = F[P[i].f2].dy - F[P[i].f1].dy + P[i].y;
        }
        while (i+1==Q[I].t && I<k)
        {

            a = find(Q[I].x);
            b = find(Q[I].y);
            if (a==b)
                ans[Q[I].index] = abs(F[Q[I].x].dx-F[Q[I].y].dx) + abs(F[Q[I].x].dy-F[Q[I].y].dy);
            else
                ans[Q[I].index] = -1;
            I++;
        }
    }
    for (int i = 0; i < k; i++)
    {
        printf("%d\n", ans[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值