poj1984 带权并查集(向量处理)

Navigation Nightmare

Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 5939   Accepted: 2102
Case Time Limit: 1000MS

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".

Input

* Line 1: Two space-separated integers: N and M

* Lines 2..M+1: Each line contains four space-separated entities, F1,
        F2, L, and D that describe a road. F1 and F2 are numbers of
        two farms connected by a road, L is its length, and D is a
        character that is either ‘N‘, ‘E‘, ‘S‘, or ‘W‘ giving the
        direction of the road from F1 to F2.

* Line M+2: A single integer, K (1 <= K <= 10,000), the number of FB‘s
        queries

* Lines M+3..M+K+2: Each line corresponds to a query from Farmer Bob
        and contains three space-separated integers: F1, F2, and I. F1
        and F2 are numbers of the two farms in the query and I is the
        index (1 <= I <= M) in the data after which Bob asks the
        query. Data index 1 is on line 2 of the input data, and so on.

Output

* Lines 1..K: One integer per line, the response to each of Bob‘s
        queries.  Each line should contain either a distance
        measurement or -1, if it is impossible to determine the
        appropriate distance.

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6 1
1 4 3
2 6 6

Sample Output

13
-1
10

Hint

At time 1, FJ knows the distance between 1 and 6 is 13. 
At time 3, the distance between 1 and 4 is still unknown.

At the end, location 6 is 3 units west and 7 north of 2, so the distance is 10.

题意:

有n个地点,m条边,对于每条边,有信息x,y,len,d,其中len表示x,y间的长度,d表示y相对于x的位置。现在有q个查询,每个查询有x,y,I,其中I表示完成I条路的时候当前2个点的状态。

思路:

首先很容易想到这事一题带权并查集的题目,因为各个点之间都有关系。但是关键在于如何处理这里的位置。现在我们用rel[x][0]表示x点到其所在树的父亲节点的向量的横坐标,rel[x][1]表示x点到其所在树的父亲节点的向量的纵坐标 ,其余的操作就是普通的带权并查集了。不过要注意一下这里的更新的操作(因为是向量)和每条边x,y的关系(更新时候谁当父节点)。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<time.h>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = 40010;
struct node
{
    int x;
    int y;
    int z;
    int id;
    char s[10];
    ll ans;
}q[10010],a[MAXN];
int pa[MAXN],n,m,k,siz[MAXN];
ll rel[MAXN][2];
void Init()
{
    for(int i = 0; i <= n; i++){
        pa[i] = i;
        siz[i] = 1;
    }
    memset(rel,0,sizeof(rel));
}
bool cmp1(node fa,node fb)
{
    return fa.z < fb.z;
}
bool cmp2(node fa,node fb)
{
    return fa.id < fb.id;
}
void getp(int& x,int& y,node fp,int flag)
{
    if(fp.s[0] == ‘E‘){
        x = fp.z;
        y = 0;
    }
    else if(fp.s[0] == ‘W‘){
        x = - fp.z;
        y = 0;
    }
    else if(fp.s[0] == ‘S‘){
        x = 0;
        y = fp.z;
    }
    else {
        x = 0;
        y = - fp.z;
    }
    if(flag)x *= -1, y *= -1;
}
int find(int x)
{
    if(x != pa[x]){
        int fx = find(pa[x]);
        siz[fx] += siz[x];
        rel[x][0] = rel[x][0] + rel[pa[x]][0];
        rel[x][1] = rel[x][1] + rel[pa[x]][1];
        pa[x] = fx;
    }
    return pa[x];
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        Init();
        for(int i = 0; i < m; i++){
            scanf("%d%d%d%s",&a[i].x,&a[i].y,&a[i].z,a[i].s);
        }
        scanf("%d",&k);
        for(int i = 0; i < k; i++){
            q[i].id = i;
            scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
        }
        sort(q,q+k,cmp1);
        int p = 0;
        for(int i = 0; i < m; i++){
            int x = a[i].x;
            int y = a[i].y;
            int tx = 0,ty = 0;
            int fx = find(x);
            int fy = find(y);
            if(fx != fy){
                if(siz[fx] > 1){
                    getp(tx,ty,a[i],0);
                    siz[fx] += siz[fy];
                    pa[fy] = fx;
                    rel[fy][0] = -rel[y][0] - tx + rel[x][0];
                    rel[fy][1] = -rel[y][1] - ty + rel[x][1];
                }
                else {
                    getp(tx,ty,a[i],1);
                    siz[fy] += siz[fx];
                    pa[fx] = fy;
                    rel[fx][0] = rel[y][0] - tx - rel[x][0];
                    rel[fx][1] = rel[y][1] - ty - rel[x][1];
                }
            }
            while(p < k && q[p].z == i + 1){
                x = q[p].x;
                y = q[p].y;
                fx = find(x);
                fy = find(y);
                if(fx != fy){
                    q[p].ans = -1;
                }
                else {
                   // cout<<rel[x][0]<<‘ ‘<<rel[y][0]<<‘ ‘<<rel[x][1]<<‘ ‘<<rel[y][1]<<endl;
                    q[p].ans = fabs(rel[x][0] - rel[y][0]) + fabs(rel[x][1] - rel[y][1]);
                }
                p ++;
            }
        }
        sort(q,q+k,cmp2);
        for(int i = 0; i < k; i++){
            printf("%lld\n",q[i].ans);
        }
    }
    return 0;
}
时间: 2024-08-13 11:49:14

poj1984 带权并查集(向量处理)的相关文章

POJ 2492 A Bug&#39;s Life (带权并查集 &amp;&amp; 向量偏移)

题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配关系. 分析 : 本题雷同POJ 1182 食物链, 如果会了那一题, 那现在这题便简单多了, 建议先了解食物链的偏移向量做法.这里也是使用向量的思考方式来进行relation的变化, 这里我令 relation = 0为同性, relation = 1为异性, 接下来的步骤就和食物链的雷同了. 优

poj1984 带权并查集

题意:有多个点,在平面上位于坐标点上,给出一些关系,表示某个点在某个点的正东/西/南/北方向多少距离,然后给出一系列询问,表示在第几个关系给出后询问某两点的曼哈顿距离,或者未知则输出-1. 只要在元素的权值上保存两个信息,与祖先元素的两个方向的差,我选择正东和正北方向差(负值表示正西和正南),然后直接用带权并查集,询问时曼哈顿距离就是两个权值的绝对值之和.由于询问是嵌在给出关系中间的,所以要先存下所有关系和询问,离线做就行. 1 #include<stdio.h> 2 #include<

POJ 1182 食物链 (带权并查集 &amp;&amp; 向量偏移)

题意 : 中文题, 直接去POJ  1182看即可 分析 : 通过普通并查集的整理归类, 能够单纯地知道某些元素是否在同一个集合内.但是题目不仅只有种类之分, 还有种类之间的关系, 即同类以及吃与被吃, 而且重点是题目问的并不是种类是否在一个集合内, 而是考察给出的关系是否矛盾.在解释之前, 先明白一个问题, 对于给出的关系, 如果我不能通过前面的信息来推断出来, 是不是不能够判断现在给出关系的对错?那就将这个信息作为真命题并存储起来, 方便后面判断.有了刚刚前面的陈述, 可以知道两个东西=>

POJ 1182 食物链(经典带权并查集 向量思维模式 很重要)

传送门: http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 90562   Accepted: 27216 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食

【HDOJ3047】Zjnu Stadium(带权并查集)

题意:浙江省第十二届大学生运动会在浙江师范大学举行,为此在浙师大建造了一座能容纳近万人的新体育场. 观众席每一行构成一个圆形,每个圆形由300个座位组成,对300个座位按照顺时针编号1到300,且可以认为有无数多行.现在比赛的组织者希望观众进入场地的顺序可以更加的有趣,在门票上并没有规定每个人的座位,而是与这个圈中某个人的相对位置,可以坐在任意一行. 门票上标示的形式如下:A B x 表示第B个人必须在A的顺时针方向x个位置(比如A坐在4号位子,x=2,则B必须坐在6号位子). 现在你就座位志愿

hihoCoder 1515 分数调查(带权并查集)

http://hihocoder.com/problemset/problem/1515 题意: 思路: 带权并查集的简单题,计算的时候利用向量法则即可. 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn = 100000+5; 5 6 int n,m,q; 7 int p[maxn],r[maxn]; 8 9 int finds(int x) 10 { 11 if(p[x

POJ 1984 Navigation Nightmare 【经典带权并查集】

任意门:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7783   Accepted: 2801 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usuall

带权并查集——食物链

并查集是常见而且好用的一种数据结构.原因在于代码简练而且方便维护各种额外信息.带权并查集就是并查集的一种应用方式.原理其实就是普通并查集额外维护了一个结点的权数组. 例题: 本题的关系有三层 -> a -> b -> c -> ,但不同的是本题的关系是有向的,也就是说a和b如果是敌对关系,那么b和a就不是敌对关系. 关系传递的本质实际上是向量的运算.还是设 d[x] 表示 x 与 fa[x] 的关系,0 代表是同类,1 代表是x吃fa[x], 根据关系图自然2就代表x被fa[x]吃

总结一下我理解的带权并查集

总结一下我理解的带权并查集 与普通并查集的区别:普通的并查集仅仅记录的是集合的关系,这个关系无非是同属一个集合或者是不在一个集合,而带权并查集是记录集合内元素的关系,而这个关系被带上了一个权值表示集合内元素之间关系的区别,例如食物链这道题,权值为0表示和根节点是同类,权值为1表示吃根节点... 用向量法来表示带权并查集 查询是否在同一个集合,或者同一个集合内的元素如何表示他们之间的关系 ??? 每个元素带一个权值用rank表示 如上图,用向量法表示则是a->root+a->b=b->ro