I - Navigation Nightmare-poj 1984

约翰和他的邻居生活在一个村庄里,他们的道路修建的很特别,都是正东正西或者正南正北,但是呢他们用一种方式描述他们和邻居的位置,比如说 6号 在1号 东面13处,那么我们就可以计算出来这两家的曼哈顿距离,也就是|x-x1| + |y-y1|, 当然这是让我们来求距离的.....
这个约翰也是比较特殊,他会一秒说出来一条道路的位置,当然在说的时候也会有一些查询,查询也是比较特别的,就是给三个参数,第一个第二个是描述的位置,第三个是时间,就是问前这些时间能不能算出他们的距离是多少?不能的话输出 -1 ,能的话输出曼哈顿距离。
分析:首先看这题想的是建立一个坐标系,让根节点是 0 0,然后可以计算根节点和他们之间的距离,不过这样的办法很难区间合并,所以pass,又想了一个办法,直接记录东西南北四个方向的位置,比方说A在B的东20,西40,这样就可以解决合并问题了,只需要把父节点的值加上也可以更新了。
////////////////////////////////////////////////////////+
竟然一下就对了........幸福来得太突然

 

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include< string.h>
#include<queue>
#include<stack>
using  namespace std;

const  int maxn =  40005;

int f[maxn];
struct Point{ int E, N;}val[maxn]; // 记录相对位置
struct node{ int u, v, len, op;}data[maxn];
int dir[ 4] = { 1, - 1, - 11}; // 代表东西南北

int Find( int x)
{
     int k = f[x];
     if(f[x] != x)
    {
        f[x] = Find(f[x]);
        val[x].E += val[k].E;
        val[x].N += val[k].N;
    }

     return f[x];
}
void Union( int u,  int v,  int len,  int op)
{
     int ru = Find(u), rv = Find(v);

     if(ru != rv)
    {
        f[rv] = ru; // 别倒着写,因为有方向是B在A的位置
        val[rv].E = -val[v].E + val[u].E + len * dir[op] * (op <  2 ?  1 :  0);
        val[rv].N = -val[v].N + val[u].N + len * dir[op] * (op >  1 ?  1 :  0);
    }
}

int main()
{
     int i, N, M;

     while(scanf( " %d%d ", &N, &M) != EOF)
    {
         char s[ 10];

         for(i= 1; i<=N; i++)
        {
            f[i] = i;
            val[i].E = val[i].N =  0;
        }

         for(i= 1; i<=M; i++)
        {
            scanf( " %d%d%d%s ", &data[i].u, &data[i].v, &data[i].len, s);
             if(s[ 0] ==  ' E ')
                data[i].op =  0;
             else  if(s[ 0] ==  ' W ')
                data[i].op =  1;
             else  if(s[ 0] ==  ' S ')
                data[i].op =  2;
             else
                data[i].op =  3;
        }

         int Q, u, v, ru, rv;

        scanf( " %d ", &Q);

        i =  1;
         while(Q--)
        {
            scanf( " %d%d%d ", &u, &v, &M);

             while(i <= M)
            {
                Union(data[i].u, data[i].v, data[i].len, data[i].op);
                i++;
            }

            ru = Find(u), rv = Find(v);

             if(ru != rv)
                printf( " -1\n ");
             else
            {
                 int ans = ( int)(fabs(val[u].E-val[v].E) + fabs(val[u].N-val[v].N));
                printf( " %d\n ", ans);
            }
        }
    }

     return  0;

} 

你可能感兴趣的:(poj)