zoukankan      html  css  js  c++  java
  • POJ 1984 Navigation Nightmare

    并查集,给n个点和m条边,每条边有方向和长度,再给q个询问,第i个询问查询两个点之间在Ti时刻时的曼哈顿距离(能连通则输出曼哈顿距离,否则输出-1)

    这题跟Corporative Network 有点像,只不过那题是维护到根节点的距离,这题还要顺便维护与根节点的x,y方向的偏移量。findset时,每次找完father就要加上father的x、y坐标偏移量,这样findset完以后就得到了与根的偏移量。然后合并时, (注意,这里是 fa[x] = y)

    dr[x].x = r.x - dr[r.u].x + dr[r.v].x;  

    dr[x].y = r.y - dr[r.u].y + dr[r.v].y;      即 x->y <==> u->v - u->x + v->y 如下图:

    这题还要注意数据可能不是按照时间顺序输入的,要做一个排序,然后再按原来的顺序输出。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define N 40100
    
    int fa[N],q;
    
    struct DR
    {
        int x,y;
    }dr[N],to[27];
    
    struct ROAD
    {
        int u,v;
        int x,y;
    }road[N];
    
    struct QUERY
    {
        int a,b,time;
        int id,res;
    }query[N];
    
    void makeset(int n)
    {
        for(int i=1;i<=n;i++)
        {
            fa[i] = i;
            dr[i].x = dr[i].y = 0;
        }
    }
    
    int findset(int x)
    {
        if(x != fa[x])
        {
            int tmp = fa[x];
            fa[x] = findset(fa[x]);
            dr[x].x += dr[tmp].x;
            dr[x].y += dr[tmp].y;
        }
        return fa[x];
    }
    
    void unionset(int index)  //合并第index条边
    {
        ROAD r = road[index];
        int x = findset(r.u);
        int y = findset(r.v);
        if(x == y)
            return;
        fa[x] = y;
        dr[x].x = r.x - dr[r.u].x + dr[r.v].x;   // x->y <==> u->v - u->x + v->y
        dr[x].y = r.y - dr[r.u].y + dr[r.v].y;   
    }
    
    int cmp1(QUERY ka,QUERY kb)
    {
        return ka.time<kb.time;
    }
    
    int cmp2(QUERY ka,QUERY kb)
    {
        return ka.id<kb.id;
    }
    
    void InitDirection()
    {
        to['E'-'A'].x = 1;
        to['E'-'A'].y = 0;
        to['W'-'A'].x = -1;
        to['W'-'A'].y = 0;
        to['N'-'A'].x = 0;
        to['N'-'A'].y = 1;
        to['S'-'A'].x = 0;
        to['S'-'A'].y = -1;
    }
    
    void read()
    {
        int n,m,i,dis;
        char ss[4];
        InitDirection();
        scanf("%d%d",&n,&m);
        makeset(n);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d %s",&road[i].u,&road[i].v,&dis,ss);
            road[i].x = dis*(to[ss[0]-'A'].x);
            road[i].y = dis*(to[ss[0]-'A'].y);
        }
        scanf("%d",&q);
        for(i=1;i<=q;i++)
        {
            scanf("%d%d%d",&query[i].a,&query[i].b,&query[i].time);
            query[i].id = i;
        }
        sort(query+1,query+q+1,cmp1);
    }
    
    void solve()
    {
        int i,j;
        j=1;
        for(i=1;i<=q;i++)
        {
            for(;j<=query[i].time;j++)
            {
                unionset(j);
            }
            if(findset(query[i].a) != findset(query[i].b))
                query[i].res = -1;
            else
                query[i].res = abs(dr[query[i].a].x-dr[query[i].b].x) + abs(dr[query[i].a].y-dr[query[i].b].y);
        }
        sort(query+1,query+q+1,cmp2);
        for(i=1;i<=q;i++)
            cout<<query[i].res<<endl;
    }
    
    int main()
    {
        read();
        solve();
        return 0;
    }
    View Code

    作者:whatbeg
    出处1:http://whatbeg.com/
    出处2:http://www.cnblogs.com/whatbeg/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    更多精彩文章抢先看?详见我的独立博客: whatbeg.com

  • 相关阅读:
    Zookeeper安装-单机版
    Centos 7 安装 Redis 5
    java利用dom4j将xml字符串转换为json
    计算机科学导论笔记-计算机组成
    计算机科学导论笔记-数据运算
    计算机科学导论笔记-数据存储
    计算机科学导论笔记-数字系统
    计算机科学导论笔记
    springmvc03
    springmvc02
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3503585.html
Copyright © 2011-2022 走看看