任意门: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), 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. 

​题意概括:

给出 M 个建树的操作,K 次查询,每次查询 x 到 y 经过前 num 次建树操作的距离,如果未联通则输出-1;

解题思路:

带权并查集,路径压缩采用向量法。

dx【i】表示 i 距离所在树根结点的横坐标

dy【i】表示 i 距离所在树根结点的纵坐标

合并 u v 过程:

先合并两棵子树

ru = getfa(u)

rv = getfa(v)

改变其中一棵子树的根结点

fa[ rv ] = ru;

更新根结点的相对值(之后子树的相对值会通过查找父结点的过程进行更新)

dx[ rv ] = dx[ u ] - dx[ v ] - wx[ u, v];

dy[ rv ] = dy[ u ] - dy[ v ] - wy[ u, v];

先执行num次建树操作

查找父结点的同时压缩路径

查询最后结果

如果相同根,直接计算两点的曼哈顿距离

否则不连通

Tip:

题目没有说查询的 num 是非递减有序的,所以处理查询前要对 num 进行排序!!!

也就是说离线处理,在线处理会出错。(虽然poj上的数据我没有排序也AC了, 但这是需要考虑的情况)

AC code:

 //离线带权并查集
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = 4e4+;
const int MAXK = 1e4+;
struct Query{int x, y, index, no;}q[MAXN]; //查询信息
int fa[MAXN], dx[MAXN], dy[MAXN]; //并查集,路径压缩(距离起点的横坐标距离 和 纵坐标距离)
int u[MAXN], v[MAXN]; //第i个操作的起点 和 终点
int ans[MAXK]; //第 k 次查询的结果
int wx[MAXN], wy[MAXN]; //wx[ i ] 第i个操作的横坐标边权 wy[ i ] 第i个操作的纵坐标边权
int N, M, K; void init()
{
for(int i = ; i <= N; i++){
fa[i] = i;
dx[i] = ;
dy[i] = ;
}
memset(q, , sizeof(q));
}
int aabs(int x){return x>?x:-x;}
int getfa(int s)
{
if(s == fa[s]) return s;
int t = fa[s];
fa[s] = getfa(fa[s]); //压缩路径
dx[s] += dx[t];
dy[s] += dy[t];
return fa[s];
}
bool cmp(Query q1,Query q2){return q1.index < q2.index;}
int main()
{
while(~scanf("%d%d", &N, &M)){
//scanf("%d%d", &N, &M);
init();
char nod;
for(int i = , d; i <= M; i++){
scanf("%d%d%d %c", &u[i], &v[i], &d, &nod);
if(nod == 'E') {wx[i] = d; wy[i] = ;}
else if(nod == 'W') {wx[i] = -d; wy[i] = ;}
else if(nod == 'N') {wy[i] = d; wx[i] = ;}
else if(nod == 'S') {wy[i] = -d; wx[i] = ;}
}
scanf("%d", &K);
for(int i = ; i <= K; i++){
scanf("%d%d%d", &q[i].x, &q[i].y, &q[i].index);
q[i].no = i;
}
sort(q+, q+K+, cmp);
int k = ;
for(int i = ; i <= K; i++){
//printf("i:%d\n", i);
while(k <= q[i].index){ //合并index个操作
//printf("k:%d\n", k);
int ru = getfa(u[k]);
int rv = getfa(v[k]);
//printf("u:%d ru:%d v:%d rv:%d\n", u[k], ru, v[k], rv);
fa[rv] = ru; //合并两个集合
dx[rv] = dx[u[k]] - dx[v[k]] - wx[k]; //
dy[rv] = dy[u[k]] - dy[v[k]] - wy[k];
k++;
}
//printf("k:%d\n", k);
if(getfa(q[i].x) != getfa(q[i].y)) ans[q[i].no] = -; //两点经过index次操作后还是没有相连
else{
ans[q[i].no] = aabs(dx[q[i].x] - dx[q[i].y]) + aabs(dy[q[i].x] - dy[q[i].y]);
}
//puts("");
}
for(int it = ; it <= K; it++) printf("%d\n", ans[it]);
}
return ;
}

一道拖了好久好久的带权并查集,给几个数据纪念一下

 Input:

    S
S
S
S
N
N
N Output:
- - Input: E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
E
S
S
S Output: - - - - - - -
- - - - - - -
-
- - - -
-
-
-

text

小蒟蒻不才,如有错误,欢迎大佬们指正~

POJ 1984 Navigation Nightmare 【经典带权并查集】的更多相关文章

  1. poj 1984 Navigation Nightmare(带权并查集+小小的技巧)

    题目链接:http://poj.org/problem?id=1984 题意:题目是说给你n个线,并告知其方向,然后对于后面有一些询问,每个询问有一个时间点,要求你输出在该时间点a,b的笛卡尔距离,如 ...

  2. 【POJ 1984】Navigation Nightmare(带权并查集)

    Navigation Nightmare Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40 ...

  3. POJ1984:Navigation Nightmare(带权并查集)

    Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7871   Accepted: 2 ...

  4. POJ 1182 食物链 (经典带权并查集)

    第三次复习了,最经典的并查集 题意:动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们 ...

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

    传送门: http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: ...

  6. POJ 1988 Cube Stacking( 带权并查集 )*

    POJ 1988 Cube Stacking( 带权并查集 ) 非常棒的一道题!借鉴"找回失去的"博客 链接:传送门 题意: P次查询,每次查询有两种: M x y 将包含x的集合 ...

  7. poj 1733 Parity game(带权并查集+离散化)

    题目链接:http://poj.org/problem?id=1733 题目大意:有一个很长很长含有01的字符串,长度可达1000000000,首先告诉你字符串的长度n,再给一个m,表示给你m条信息, ...

  8. HDU 3038 - How Many Answers Are Wrong - [经典带权并查集]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...

  9. POJ 1733 Parity game(离散化+带权并查集)

    离散化+带权并查集 题意:长度为n的0和1组成的字符串,然后问第L和R位置之间有奇数个1还是偶数个1. 根据这些回答, 判断第几个是错误(和之前有矛盾)的. 思路:此题同HDU 3038 差不多,询问 ...

随机推荐

  1. DP Intro - Tree DP

    二叉苹果树 题目 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点 ...

  2. [转]Asp.net MVC中的ViewData与ViewBag

    本文转自:http://www.cnblogs.com/wintersun/archive/2012/01/21/2328563.html 在Asp.net MVC 3 web应用程序中,我们会用到V ...

  3. LaTeX 修订

    LaTeX多人协同编辑的时候,修订起来与word相比较而言麻烦一些.不过随着技术的发展和需求的增多,会有越来越多的工具支持LaTeX的修订. (1)在线LaTeX ShareLaTeX是一个很优秀的在 ...

  4. Mysql只Union用法

    MYSQL中的UNION UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果. 举例说明: select * from table1 u ...

  5. 在MyEclipse中使用javadoc导出API文档详解

    本篇文档介绍如何在MyEclipse中导出javadoc(API)帮助文档,并且使用htmlhelp.exe和jd2chm.exe生成chm文档. 具体步骤如下: 打开MyEclipse,选中想要制作 ...

  6. 了解WaitForSingleObject中WAIT_ABANDONED 返回值

    1.互斥量内核对象 互斥量内核对象用来确保一个线程独占对一个资源的访问.互斥量对象包含一个使用计数.线程ID以及递归计数.互斥量与关键段的行为完全相同.但是互斥量是内核对象,而关键段是用户模式下的同步 ...

  7. glyphicons-halflings-regular.woff2 文件 404

    搜索了下,果然是因为mine没有配置的原因. http://stackoverflow.com/questions/32300578/how-to-remove-error-about-glyphic ...

  8. Linux 网络(连接)相关参数作用

    参考: [1] http://bbs.chinaunix.net/thread-2318039-1-1.html Backlog net.core.netdev_max_backlog = 1000 ...

  9. 对 Vue 的理解(一)

    一.什么是 Vue ? 首先,Vue 是一个 MVVM 框架,M -- 模型,就是用来定义驱动的数据,V -- 视图,是经过数据改变后的 html,VM -- 框架视图,就是用来实现双向绑定的中间桥梁 ...

  10. 常见的media断点

    landscape mode是指宽度比高度宽的模式,也就是俗称的宽屏模式: portrait mode是指高度比宽度高的模式,也就是俗称的竖屏模式: /*#region SmartPhones */ ...