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 如下图:

POJ 1984 Navigation Nightmare

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

 

代码:

#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

 

你可能感兴趣的:(poj)