题意:
按顺序给出两个节点之间的距离和方向,求在某一时刻两个点之间的曼哈顿距离。
思路:
因为需要求某个时刻的曼哈顿距离,所以要将所有的数据存起来离线操作。
规定向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;
}