POJ1984 Navigation Nightmare(并查集)
来源:互联网 发布:学编程从什么开始学 编辑:程序博客网 时间:2024/06/03 19:30
题意:有N个农场,连接这些农场的路只有水平的和竖直的。给出M条信息(f1 f2 L D),说明f2在f1的D方向L距离处。给出k次查询(f1 f2 index),意为根据给出的前index条信息,f1和f2的最短距离是否能确定,可以的话就输出最短距离,否则输出-1.显然这里的最短距离是横、纵方向的最短距离之和。
思路:显然题目需要多次判断是否属于同一集合,要用并查集。将平面看作二维直角坐标系,这样每个节点只需保存父节点值和到父节点的x、y轴距离。开始偷懒没有路径压缩果断TLE,无奈的加上T_T。找到根节点后压缩路径时需要多维护一个当前累计偏移量,用于更新当前点关于根节点的偏移。任意两点之间可以看作一个向量,画个图就明白了。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;const int inf = 0x3f3f3f3f;const int mod = 1000000007;const int maxn = 40005;struct query{ int a,b,ind,pos; bool operator < (const query &b)const{ return ind < b.ind; }}qry[10005];//记录k次查询struct node{ int x,y,fa;}farm[maxn];//farm[i]记录第i个点的父节点和到父节点的距离struct relation{ int a,b,dis; char ch;}rel[maxn];//记录输入的位置关系int n,m,k,ans[10005];int find(int cur, int &x, int &y){ int tmp, _cur = cur, dx = 0, dy = 0, tmpx, tmpy; while(cur != farm[cur].fa){ x += farm[cur].x; y += farm[cur].y; cur = farm[cur].fa; } /*tmp、tmpx、tmpy临时变量 dx、dy记录路径压缩到当前点时从初始点累计到当前点的偏移 用初始点到根节点的总偏移x、y减去dx、dy就可以得到终点相对当前点的偏移啦 */ while(_cur != cur){ tmpx = x - dx; tmpy = y - dy; dx += farm[_cur].x; dy += farm[_cur].y; farm[_cur].x = tmpx; farm[_cur].y = tmpy; tmp = _cur; _cur = farm[_cur].fa; farm[tmp].fa = cur; } return cur;}int main(){ int x1,x2,y1,y2,dx,dy; char dic; while(~scanf("%d%d", &n, &m)){ for(int i=1; i<=n; ++i){ farm[i].fa = i; farm[i].x = farm[i].y = 0; } for(int i=1; i<=m; ++i){ scanf("%d%d%d %c", &rel[i].a, &rel[i].b, &rel[i].dis, &rel[i].ch); getchar(); } scanf("%d", &k); for(int i=1; i<=k; ++i){ scanf("%d%d%d", &qry[i].a, &qry[i].b, &qry[i].ind); qry[i].pos = i; } sort(qry + 1, qry + k + 1);//按index排序 for(int i=1, j=1; i<=k; ++i){ for(; j<=qry[i].ind; ++j){ x1 = x2 = y1 = y2 = dx = dy = 0; if(rel[j].ch == 'N') dy = rel[j].dis; if(rel[j].ch == 'S') dy = -rel[j].dis; if(rel[j].ch == 'W') dx = -rel[j].dis; if(rel[j].ch == 'E') dx = rel[j].dis; int fa = find(rel[j].a, x1, y1); int fb = find(rel[j].b, x2, y2); if(fa != fb){//合并结点时不仅要更新父节点值,还要更新x、y farm[fa].fa = fb; farm[fa].x = dx + x2 -x1; farm[fa].y = dy + y2 -y1; } } x1 = x2 = y1 = y2 = 0; int fa = find(qry[i].a, x1, y1); int fb = find(qry[i].b, x2, y2); if(fa != fb){ ans[qry[i].pos] = -1; } else { ans[qry[i].pos] = abs(x1 - x2) + abs(y1 - y2); } } for(int i=1; i<=k; ++i){ printf("%d\n", ans[i]); } } return 0;}
阅读全文
0 0
- POJ1984 Navigation Nightmare(并查集)
- poj1984 Navigation Nightmare(并查集)
- poj1984 Navigation Nightmare(带权并查集)
- kungbin专题五 并查集 POJ1984 Navigation Nightmare
- poj1984(并查集)
- Navigation Nightmare(并查集(多权值更新))
- POJ 1984 Navigation Nightmare (数据结构-并查集)
- POJ 1984 Navigation Nightmare(加权并查集)
- POJ 1984 Navigation Nightmare (带权并查集)
- poj 1984 Navigation Nightmare(带权并查集)
- 【POJ 1984】Navigation Nightmare (并查集)
- POJ--1984-Navigation Nightmare--并查集
- poj 1984 - Navigation Nightmare(并查集)
- POJ 1984 Navigation Nightmare 并查集
- [POJ1984]Navigation Nightmare交通噩梦
- PKU 1984 Navigation Nightmare dfs+并查集
- POJ 1984 Navigation Nightmare【并查集思路总结】
- poj 1984 Navigation Nightmare(带权并查集)
- 马克飞象与印象笔记的双剑合璧
- 一个整数数组,每个数字都出现K次,只有一个数字出现M次,找出这个数字(线性时间)
- python的type 和object
- Docker--I'm here(二)思想
- ZooKeeper 学习 (二) ZAB协议简单总结
- POJ1984 Navigation Nightmare(并查集)
- Java 内部类原理解析
- HDU 6040 Hints of sd0061 stl
- Java-synchronize和lock详解(转)
- oop
- POJ3041:Asteroids(二分图匹配)
- HDU 6035 Colorful Tree
- JDK源码分析之主要阻塞队列实现类LinkedBlockingQueue
- 杂记-路由器上网设置:输入路由器设置网址却登陆至猫