Navigation Nightmare——带权并查集(多权值)

Posted j666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Navigation Nightmare——带权并查集(多权值)相关的知识,希望对你有一定的参考价值。

题目链接

题意:

给出n个农场,然后按时间依次给出m个关于农场相对位置的信息,之后会给出询问,问在t时刻,x到y的曼哈顿距离是多少。

题解:

dx【i】维护 根节点到 i 的横坐标距离   dy【i】维护 根节点到 i 的纵坐标距离

并查集高效的地方就在于在使用Find(x)函数查找x的父结点的时候会把沿途递归访问到的所有结点直接连到父节点上,使得下一次查询可以直接找到父节点,代码表示就是f[x]=Find(f[x]);

之前接触到的都是比较裸的并查集,但就像这题,维护并查集的时候还需要维护点到其父节点的距离(dx[x]+=dx[f[x]];),再构造Find(x)函数时就得同时考虑对距离的维护,维护方式一旦不对就有可能导致距离错误。

维护连通块内的结点到父节点的横坐标距离和纵坐标的距离,查询时先判断是否属于同一个集合内 若属于则将两点到父节点的横轴距离和纵轴距离相减求得曼哈顿距离即可

重点是如何进行集合合并

 

先让 fx指向fy 即 f[fy]=fx  然后分情况讨论

如果 d==W  dx【fx】= dx【a[i].f2】 - dx【a[i].f1】- a【i】.l   dy【fx】=dy【a[i].f2】-dy【a[i].f1】

如果 d==E  dx【fx】= dx【a[i].f2】 - dx【a[i].f1】+ a【i】.l   dy[fx]=dy【a[i].f2】-dy【a[i].f1】

如果 d==S  dy【fx】= dy【a[i].f2】 - dy【a[i].f1】+ a【i】.l   dx[fx]=dx【a[i].f2】-dx【a[i].f1】

如果 d==N  dy【fx】= dy【a[i].f2】 - dy【a[i].f1】- a【i】.l    dx[fx]=dx【a[i].f2】-dx【a[i].f1】

然后将上面四种情况合并

 

代码:

技术图片
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 2e5+7;
int f[maxn],dx[maxn],dy[maxn];
struct node

    int f1,f2,l;
    char d;
 a[maxn];
int n,m,k;
int Find(int x)

    if(f[x]==x)return x;
    int root=Find(f[x]);
    dx[x]+=dx[f[x]];
    dy[x]+=dy[f[x]];
    return f[x]=root;


int main()

    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++)f[i]=i;
    for(int i=1;i<=m;i++)
    
        scanf("%d%d%d",&a[i].f1,&a[i].f2,&a[i].l);
        cin>>a[i].d;
    
    scanf("%d",&k);

    int i=1;
    while(k--)
    
        int F1,F2,L;
        scanf("%d%d%d",&F1,&F2,&L);
        while(i<=L)
        
            int fx=Find(a[i].f1);
            int fy=Find(a[i].f2);
            if(fx!=fy)
            
                f[fx]=fy;

                dx[fx]=dx[a[i].f2]-dx[a[i].f1];
                dy[fx]=dy[a[i].f2]-dy[a[i].f1];

                if(a[i].d==W) dx[fx]-=a[i].l;
                else if(a[i].d==E)dx[fx]+=a[i].l;
                else if(a[i].d==S)dy[fx]+=a[i].l;
                else dy[fx]-=a[i].l;
            
            i++;
        
        int fx=Find(F1);
        int fy=Find(F2);
        if(fx!=fy)printf("-1\n");
        else
        
            int ans=abs(dx[F1]-dx[F2])+abs(dy[F1]-dy[F2]);
            printf("%d\n",ans);
        

    

    return 0;
View Code

 

以上是关于Navigation Nightmare——带权并查集(多权值)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1984 - Navigation Nightmare - [带权并查集]

POJ 1984 Navigation Nightmare 经典带权并查集

BZOJ 3362 Navigation Nightmare 带权并查集

POJ-1984-Navigation Nightmare+带权并查集(中级

Navigation Nightmare——带权并查集(多权值)

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