BZOJ_3362_[Usaco2004 Feb]Navigation Nightmare 导航噩梦_并查集

Description

农夫约翰有N(2≤N≤40000)个农场,标号1到N,M(2≤M≤40000)条的不同的垂直或水

平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样,

图中农场用F1..F7表示, 每个农场最多能在东西南北四个方向连结4个不同的农场.此外,农场只处在道路的两端.道路不会交叉且每对农场间有且仅有一条路径.邻居鲍伯要约翰来导航,但约翰丢了农场的地图,他只得从电脑的备份中修复了.每一条道路的信息如下:

从农场23往南经距离10到达农场17

从农场1往东经距离7到达农场17

当约翰重新获得这些数据时,他有时被的鲍伯的问题打断:“农场1到农场23的曼哈顿距离是多少?”所谓在(XI,Yi)和(X2,y2)之间的“曼哈顿距离”,就是lxl - X21+lyl - y21.如果已经有足够的信息,约翰就会回答这样的问题(在上例中答案是17),否则他会诚恳地抱歉并回答-1.

Input

第1行:两个分开的整数N和M.

第2到M+1行:每行包括4个分开的内容,F1,F2,三,D分别描述两个农场的编号,道路的长度,F1到F2的方向N,E,S,w.

第M+2行:一个整数,K(1≤K≤10000),表示问题个数.

第M+3到M+K+2行:每行表示一个问题,由3部分组成:Fi,F2,,.其中Fi和F2表示两个被问及的农场.而/(1≤J≤M)表示问题提出的时刻.J为1时,表示得知信息1但未得知信息2时.

Output

第1到K行:每行一个整数,回答问题.表示两个农场间的曼哈顿距离.不得而知则输出-1.

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


将询问排序,每次插边。

用并查集维护出祖先和到祖先的横向距离和纵向距离,find时更新。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 40050
int n,fa[N],xx[N],yy[N],m,ans[N];
char opt[10];
int Abs(int x) {
    return x>0?x:-x;
}
struct E {
    int a,b,c,d;
    void rd() {
        scanf("%d%d%d%s",&a,&b,&c,opt);
        if(opt[0]==‘N‘) d=1;
        if(opt[0]==‘S‘) d=2;
        if(opt[0]==‘W‘) d=3;
        if(opt[0]==‘E‘) d=4;
    }
}e[N];
struct Q {
    int t,x,y,id;
    void rd(){scanf("%d%d%d",&x,&y,&t);}
    bool operator < (const Q &u) const {
        return t<u.t;
    }
}q[N];
int find(int x) {
    if(fa[x]==x) return x;
    int tmp=fa[x];
    fa[x]=find(fa[x]);
    xx[x]+=xx[tmp];
    yy[x]+=yy[tmp];
    return fa[x];
}
void add(int x) {
    int a=e[x].a,b=e[x].b,c=e[x].c,d=e[x].d;
    int da=find(a),db=find(b);
    fa[da]=db;
    // if(ta != tb) f[ta] = tb , dx[ta] = dx[b[t]] + cx[t] - dx[a[t]] , dy[ta] = dy[b[t]] + cy[t] - dy[a[t]];
    if(d==1) {
        xx[da]=xx[b]-xx[a];
        yy[da]=yy[b]-yy[a]-c;
    }else if(d==2) {
        xx[da]=xx[b]-xx[a];
        yy[da]=yy[b]-yy[a]+c;
    }else if(d==3) {
        xx[da]=xx[b]-xx[a]-c;
        yy[da]=yy[b]-yy[a];
    }else {
        xx[da]=xx[b]-xx[a]+c;
        yy[da]=yy[b]-yy[a];
    }
}
int query(int x,int y) {
    int dx=find(x),dy=find(y);
    if(dx!=dy) return -1;
    return Abs(xx[x]-xx[y])+Abs(yy[x]-yy[y]);
}
int main() {
    scanf("%d%*d",&n);
    int i;
    for(i=1;i<=n;i++) fa[i]=i;
    for(i=1;i<n;i++) {
        e[i].rd();
    }
    scanf("%d",&m);
    for(i=1;i<=m;i++) {
        q[i].rd(); q[i].id=i;
    }
    sort(q+1,q+m+1);
    int now=1;
    for(i=1;i<=m;i++) {
        while(now<=q[i].t) {
            add(now); now++;
        }
        ans[q[i].id]=query(q[i].x,q[i].y);
    }
    for(i=1;i<=m;i++) {
        printf("%d\n",ans[i]);
    }
}

原文地址:https://www.cnblogs.com/suika/p/9062502.html

时间: 2024-10-14 05:41:50

BZOJ_3362_[Usaco2004 Feb]Navigation Nightmare 导航噩梦_并查集的相关文章

BZOJ3362 [Usaco2004 Feb]Navigation Nightmare 导航噩梦

题目大意:自行脑补. 思路:维护两个维度上的带权并查集即可. 注意对于题目给出的一堆关系,我们应该添加两对关系. Code: #include <cstdio> #include <cstring> #include <cctype> #include <iostream> #include <algorithm> using namespace std; #define N 40010 int n, m; struct UnionSet {  

BZOJ 3362: [Usaco2004 Feb]Navigation Nightmare 导航噩梦

Description 给你每个点与相邻点的距离和方向,求两点间的曼哈顿距离. \(n \leqslant 4\times 10^4\) . Sol 加权并查集. 像向量合成一样合并就可以了,找 \(f[x]\) 的时候需要先记录现在的父节点,然后更新他新的父节点. Code /************************************************************** Problem: 3362 User: BeiYu Language: C++ Result:

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

Navigation Nightmare 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 <= 100

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

题目链接:http://poj.org/problem?id=1984 题意:题目是说给你n个线,并告知其方向,然后对于后面有一些询问,每个询问有一个时间点,要求你输出在该时间点a,b的笛卡尔距离,如果不存在则输出-1 其实就是将权值分一下x,y,x表示x轴方向的权值,y表示y轴方向的权值.然后最后询问时稍微有点技巧 可以先记录一下每次询问的位置然后再按照时间点从小到大来排序最后这样就方便并查集了. #include <iostream> #include <cstring> #i

nyoj925_国王的烦恼_并查集

国王的烦恼 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛.两个小岛间可能存在多座桥连接.然而,由于海水冲刷,有一些大桥面临着不能使用的危险.如果两个小岛间的所有大桥都不能使用,则这两座小岛就不能直接到达了.然而,只要这两座小岛的居民能通过其他的桥或者其他的小岛互相到达,他们就会安然无事.但是,如果前一天两个小岛之间还有方法可以到达,后一天却不能到达了,居民们就会一起发起抗议

Farm Irrigation_深搜_并查集

Farm Irrigation TimeLimit: 2000/1000 MS (Java/Others)  MemoryLimit: 65536/32768 K (Java/Others) 64-bit integer IO format:%I64d Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is divided into a lot of

jzoj 2936_逐个击破_并查集

题目描述 三大战役的平津战场上,傅作义集团在以北平.天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜.为了就地歼敌不让其逃走,maozedong制定了先切断敌人东洒两头退路然后再逐个歼灭敌人的战略方针. 秉承伟大军事家的战略思想,作为一个有智慧的军长你,遇到了一个类似的战场局面: 现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花

poj1182食物链_并查集_挑战程序设计竞赛例题

食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 65534   Accepted: 19321 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A.  现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种.  有人用两种说法对这N个动物所构成的食物链关系进行描述:  第一种说法是"1 X Y",表示X和

Navigation Nightmare---poj1984(多关系并查集)

题目链接:http://poj.org/problem?id=1984 给定n个城市,m条边告诉你城市间的相对距离,接下来q组询问,问你在第几条边添加后两城市的距离. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <map> #i