POJ1984 Navigation Nightmare (hard?or!hard?)

Description
Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series of M (1 <= M < 40,000) vertical and horizontal roads each of varying lengths (1 <= length <= 1000) connect the farms. A map of these farms might look something like the illustration below in which farms are labeled F1..F7 for clarity and lengths between connected farms are shown as (n):
F1 --- (13) ---- F6 --- (9) ----- F3
| |
(3) |
| (7)
F4 --- (20) -------- F2 |
| |
(2) F5

F7 
Being an ASCII diagram, it is not precisely to scale, of course.

Each farm can connect directly to at most four other farms via roads that lead exactly north, south, east, and/or west. Moreover, farms are only located at the endpoints of roads, and some farm can be found at every endpoint of every road. No two roads cross, and precisely one path 
(sequence of roads) links every pair of farms.

FJ lost his paper copy of the farm map and he wants to reconstruct it from backup information on his computer. This data contains lines like the following, one for every road:

There is a road of length 10 running north from Farm #23 to Farm #17
There is a road of length 7 running east from Farm #1 to Farm #17
...

As FJ is retrieving this data, he is occasionally interrupted by questions such as the following that he receives from his navigationally-challenged neighbor, farmer Bob:

What is the Manhattan distance between farms #1 and #23?

FJ answers Bob, when he can (sometimes he doesn't yet have enough data yet). In the example above, the answer would be 17, since Bob wants to know the "Manhattan" distance between the pair of farms.
The Manhattan distance between two points (x1,y1) and (x2,y2) is just |x1-x2| + |y1-y2| (which is the distance a taxicab in a large city must travel over city streets in a perfect grid to connect two x,y points).

When Bob asks about a particular pair of farms, FJ might not yet have enough information to deduce the distance between them; in this case, FJ apologizes profusely and replies with "-1". 



 题目大意:在1。。。m的时间里,每秒给两点、两点间的路长、路的东西南北。之后的k行中给出了k个询问,相应询问给出了两个节点和询问时间(不一定按升序排列),如果能到,则输出曼哈顿距离,否则输出-1。

思路:离线操作,对于访问时间排升序(置一个top指针,跟着边走),最后输出的时候注意按输入顺序输出就好了。对点进行并查集,但是tot数组要保存横向和纵向的位移(有正负)。规定向南和向东为正方向,有点奇怪,不过画到图上好像好看一点。。。然后就是对于合并时的结点更新。。。
                if (b[i].di=='E'||b[i].di=='W')
    {
    sum[r2][0]=sum[b[i].st][0]-sum[b[i].en][0]-b[i].va;
    sum[r2][1]=sum[b[i].st][1]-sum[b[i].en][1];
    }
    else
    {
    sum[r2][0]=sum[b[i].st][0]-sum[b[i].en][0];
    sum[r2][1]=sum[b[i].st][1]-sum[b[i].en][1]-b[i].va;
    }
    fa[r2]=r1;

code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct use{
int st,en,ti,yu;
}a[40001];
struct user{
int st,en,va;
char di;
}b[40001];
int fa[40001]={0},sum[40001][2]={0},ans[40001]={0};
int my_comp(const use &x,const use &y)
{
if (x.ti<y.ti) return 1;
    else return 0;
}
int rool(int x)
{
int j;
if (fa[x]!=x) 
{
j=rool(fa[x]);
sum[x][0]=sum[x][0]+sum[fa[x]][0];
sum[x][1]=sum[x][1]+sum[fa[x]][1];
fa[x]=j;
}
return fa[x];
}
int main()
{
int i,j,n,m,k,r1,r2,t,top;
char ch;
scanf("%d%d",&n,&m);
for (i=1;i<=m;++i)
{
scanf("%d%d%d",&b[i].st,&b[i].en,&b[i].va);
cin>>b[i].di;
if (b[i].di=='E'||b[i].di=='N')
 b[i].va=-1*b[i].va;
    }
scanf("%d",&k);
    for (i=1;i<=k;++i)
    {
      scanf("%d%d%d",&a[i].st,&a[i].en,&a[i].ti);
      a[i].yu=i;
}
sort(a+1,a+k+1,my_comp);
    top=1;
    for (i=1;i<=n;++i)
      fa[i]=i;
    for (i=1;i<=m;++i)
    {
   
    r1=rool(b[i].st);
    r2=rool(b[i].en);
    if (r1!=r2)
    {
    if (b[i].di=='E'||b[i].di=='W')
    {
    sum[r2][0]=sum[b[i].st][0]-sum[b[i].en][0]-b[i].va;
    sum[r2][1]=sum[b[i].st][1]-sum[b[i].en][1];
    }
    else
    {
    sum[r2][0]=sum[b[i].st][0]-sum[b[i].en][0];
    sum[r2][1]=sum[b[i].st][1]-sum[b[i].en][1]-b[i].va;
    }
    fa[r2]=r1;
    }
if (top>k) break;
    while (a[top].ti==i&&top<=k)
    {
    r1=rool(a[top].st);
    r2=rool(a[top].en);
    if (r1!=r2)
      ans[a[top].yu]=-1;
    else 
    {
      ans[a[top].yu]=abs(sum[a[top].st][0]-sum[a[top].en][0])
                +abs(sum[a[top].st][1]-sum[a[top].en][1]);
            }
            ++top;
}
    }
    for (i=1;i<=k;++i)
      printf("%d\n",ans[i]);

你可能感兴趣的:(poj)