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 {

    int

root[N], dis[N];

    void

reset() {

        int

i;

        for(i
= 1; i <= n; ++i)

            root[i]
= i, dis[i] = 0;

    }

    int

find(
int

x) {

        static

int

stack[N];

        int

top = 0;

        for(;
x != root[x]; x = root[x])

            stack[++top]
= x;

        for(int

i = top - 1; i >= 1; --i)

            dis[stack[i]]
+= dis[stack[i + 1]], root[stack[i]] = x;

        return

x;

    }

}Set[2];

#define
K 10010

struct

Ask {

    int

u, v, tclock, lab;

    void

read(
int

_) {

        lab
= _;

        scanf("%d%d%d",
&u, &v, &tclock);

    }

    bool

operator < (
const

Ask &B)
const

{

        return

tclock < B.tclock;

    }

}S[K];

int

ans[K];

#define
M 40010

int

u[M], v[M], d[M];

bool

vec[M];

#define
_abs(x) ((x)>0?(x):-(x))

int

main() {

    #ifndef
ONLINE_JUDGE

    freopen("tt.in",
"r",
stdin);

    #endif

    

    scanf("%d%d",
&n, &m);

    

    register

int

i, j;

    

    int

a, b, x;

    char

s[10];

    for(i
= 1; i <= m; ++i) {

        scanf("%d%d%d%s",
&a, &b, &x, s);

        d[i]
= x;

        if

(s[0] ==
‘E‘)

            u[i]
= a, v[i] = b, vec[i] = 0;

        else

if

(s[0] ==
‘W‘)

            u[i]
= b, v[i] = a, vec[i] = 0;

        else

if

(s[0] ==
‘N‘)

            u[i]
= a, v[i] = b, vec[i] = 1;

        else

            u[i]
= b, v[i] = a, vec[i] = 1;

    }

    

    int

Q;

    scanf("%d",
&Q);

    for(i
= 1; i <= Q; ++i)

        S[i].read(i);

    sort(S
+ 1, S + Q + 1);

    

    Set[0].reset(),
Set[1].reset();

    

    int

ra, rb;

    j
= 1;

    for(i
= 1; i <= m; ++i) {

        ra
= Set[vec[i]].find(u[i]);

        rb
= Set[vec[i]].find(v[i]);

        Set[vec[i]].root[ra]
= rb;

        Set[vec[i]].dis[ra]
= d[i] + Set[vec[i]].dis[v[i]] - Set[vec[i]].dis[u[i]];

        

        ra
= Set[1 - vec[i]].find(u[i]);

        rb
= Set[1 - vec[i]].find(v[i]);

        Set[1
- vec[i]].root[ra] = rb;

        Set[1
- vec[i]].dis[ra] = Set[1 - vec[i]].dis[v[i]] - Set[1 - vec[i]].dis[u[i]];

        

        for(;
S[j].tclock == i; ++j) {

            ra
= Set[0].find(S[j].u), rb = Set[0].find(S[j].v);

            if

(ra != rb) {

                ans[S[j].lab]
= -1;

                continue;

            }

            ans[S[j].lab]
+= _abs(Set[0].dis[S[j].u] - Set[0].dis[S[j].v]);

            ra
= Set[1].find(S[j].u), rb = Set[1].find(S[j].v);

            if

(ra != rb) {

                ans[S[j].lab]
= -1;

                continue;

            }

            ans[S[j].lab]
+= _abs(Set[1].dis[S[j].u] - Set[1].dis[S[j].v]);

        }

    }

    

    for(i
= 1; i <= Q; ++i)

        printf("%d\n",
ans[i]);

    

    return

0;

}

时间: 2024-08-01 04:10:01

BZOJ3362 [Usaco2004 Feb]Navigation Nightmare 导航噩梦的相关文章

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往

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 二维带权并查集

题目来源:POJ 1984 Navigation Nightmare 题意:给你一颗树 k次询问 求2点之间的曼哈顿距离 并且要在只有开始k条边的情况下 思路:按照方向 我是以左上角为根 左上角为原点 dx[i]为i点距离根的x坐标 dy[]是y坐标 这两个可以通过路径压缩求出 只不过是二维而已 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int m

POJ 1984 Navigation Nightmare (数据结构-并查集)

Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 4072   Accepted: 1615 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series o

【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

bzoj3367[Usaco2004 Feb]The Big Game 球赛*

bzoj3367[Usaco2004 Feb]The Big Game 球赛 题意: n只奶牛,每只支持两个球队中的一个,它们依次上车,上到一定程度可以开走这辆车并换下一辆继续上.要求一辆车上支持不同球队的奶牛数的差≤I,或者这辆车上只有支持同一球队的牛.问通过安排换车时机所能得到的车数的最小值.n≤2500. 题解: f[i]=f[j]+1,abs(sum[0][i]-sum[0][j]-sum[1][i]+sum[1][j])<=I||sum[0][i]==sum[0][j]||sum[1]

BZOJ 3367: [Usaco2004 Feb]The Big Game 球赛( dp )

dp(i)表示前i个人最少坐多少辆车, dp(i) = min(dp(j) + 1, dp(i)) (0 <= j < i 且 (i, j]的人能坐在一辆车上) 时间复杂度O(n²) --------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; const int maxn = 2509; int sum

树的直径 【bzoj3363】[Usaco2004 Feb]Cow Marathon 奶牛马拉松

3363: [Usaco2004 Feb]Cow Marathon 奶牛马拉松 Description ? 最近美国过度肥胖非常普遍,农夫约翰为了让他的奶牛多做运动,举办了奶牛马拉松.马拉 松路线要尽量长,所以,告诉你农场的地图(该地图的描述与上题一致),请帮助约翰寻找两个 最远农场间的距离. Input ? 第1行:两个分开的整数N和M. ? 第2到M+1行:每行包括4个分开的内容,Fi,F2,L,D分别描述两个农场的编号,道路的长 度,F1到F2的方向N,E,S,W. Output ? 一个

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