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

35 篇文章 0 订阅
12 篇文章 0 订阅

愚蠢的我才刚会打带权并查集呢。。

每个点要用两个权值记录 x y 即他与父亲节点的相对距离

然后并查集的时候 加起来就好了

接着自定义一下咯 什么东是x+1之类的

每次知道两个点 x 到 y的距离 把fa[fx]=fy fx到fy的距离就是 fx->x->y->fy

(其实自己用向量yy一下就好,fx->x就用x->fx反过来就好)

注意 题目是 U V E/W/N/S 是指U在V 的...侧 别看错了

对了 这题的读入略恶心啊。 温馨提示POJ的询问是有序的 BZOJ上的是无序的

放个两个都能过的代码吧。(重载运算符还是挺爽的)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=40008,inf=1e9;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
struct node{
    int x,y;
    node(){}
    node(int a,int b){x=a;y=b;}
    node operator +(const node &a){return node(a.x+x,a.y+y);}
    node operator -(const node &a){return node(a.x-x,a.y-y);}
}p[N];
int dis(node x){return abs(x.x)+abs(x.y);}
struct o{int x,y; node u;}a[N];
struct g{int x,y,t,id;}l[N>>2];
int Cmp(g x1,g x2){return x1.t<x2.t;}
int f[N],n,m,q,ans[N>>2];
int fa(int x)
{
    if(x==f[x])return x;
    int y=f[x];
    f[x]=fa(f[x]),p[x]=p[x]+p[y];
    return f[x];
}
int main()
{
    int i,j,x,y,c,qx,qy; char ch;
    n=read(),m=read();
    for(i=1;i<=n;i++)f[i]=i;
    for(i=1;i<=m;i++)
    {
        a[i].x=read(),a[i].y=read(),c=read();
        scanf("\n%c",&ch);
        if(ch=='E')a[i].u.x=c;
        if(ch=='W')a[i].u.x=-c;
        if(ch=='N')a[i].u.y=c;
        if(ch=='S')a[i].u.y=-c;
    }
    q=read();
    for(i=1;i<=q;i++)
        l[i].x=read(),l[i].y=read(),l[i].t=read(),l[i].id=i;
    sort(l+1,l+1+q,Cmp);
    for(i=j=1;i<=q;i++)
    {
        for(;j<=l[i].t;j++)
        {
            x=fa(a[j].x),y=fa(a[j].y);
            f[x]=y; p[x]=p[a[j].y]-p[a[j].x]-a[j].u;
        }
        x=fa(l[i].x),y=fa(l[i].y);
        if(x!=y)ans[l[i].id]=-1;
        else ans[l[i].id]=dis(p[l[i].x]-p[l[i].y]);
    }
    for(i=1;i<=q;i++)printf("%d\n",ans[i]);
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值