码迷,mamicode.com
首页 > Web开发 > 详细

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

时间:2019-10-01 16:19:01      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:nbsp   poj   图片   problem   需要   还需要   重点   include   vector   

题目链接

题意:

给出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——带权并查集(多权值)

标签:nbsp   poj   图片   problem   需要   还需要   重点   include   vector   

原文地址:https://www.cnblogs.com/j666/p/11615378.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!