poj1984 Navigation Nightmare(带权并查集)

来源:互联网 发布:边际递减效应爱情知乎 编辑:程序博客网 时间:2024/06/06 03:18


http://poj.org/problem?id=1984

题意:n个点,m个输入边,边中有权值和方向,q个查询,查询两点之间的最短路。


ps:好题,不过题目真尼玛长,这一道阅读的量啊。里面的index是啥始终看不懂,后来才知道每加入一条边需要1时间,而这个查询就是时间的限制。这题和poj1986很像,但是这题查询时两点不一定有关系,相当于在线,边输入边查询。而1986是离线,先就已经给了一个图。不要搞混。


思路:带权并查集,其实带权和关系一个意思。由于对距离的计算分为x方向和y方向,所以记得特殊处理。合并时下面的关系也同步更新,运用向量法。记得永远都是当前节点指向根。后来因为得数把减号写成加号WA了好几次= =



#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;typedef long long LL;const int N = 100010;const int INF = 0x3f3f3f3f;int pre[N], disx[N], disy[N], n;struct node{    int u, v, len;    char s[5];}edge[N];int Find(int x){    if(x == pre[x]) return x;    int tmp = pre[x];    pre[x] = Find(pre[x]);    disx[x] += disx[tmp];    disy[x] += disy[tmp];    return pre[x];}void Union(int x, int y, int dx, int dy){    int rx = Find(x);    int ry = Find(y);    pre[ry] = rx;    disx[ry] = disx[x]-disx[y]+dx;    disy[ry] = disy[x]-disy[y]+dy;}void init(){    memset(disx, 0, sizeof(disx));    memset(disy, 0, sizeof(disy));    for(int i = 1; i <= n; i++)        pre[i] = i;}int main(){  //  freopen("in.txt", "r", stdin);    int m, x, y, k, q, time;    scanf("%d%d", &n, &m);    init();    for(int i = 0; i < m; i++)    {        scanf("%d%d%d%s", &edge[i].u, &edge[i].v, &edge[i].len, edge[i].s);    }    scanf("%d", &q);    for(int i = 0, k = 0; i < q; i++)    {        scanf("%d%d%d", &x, &y, &time);        for(int j = k; j < time; j++)        {            int dx = 0, dy = 0;            switch(edge[j].s[0])            {                case 'E':                {                    dx += edge[j].len;                    break;                }                case 'W':                {                    dx -= edge[j].len;                    break;                }                case 'N':                {                    dy += edge[j].len;                    break;                }                case 'S':                {                    dy -= edge[j].len;                    break;                }            }            Union(edge[j].u, edge[j].v, dx, dy);        }        k = time;        int rx = Find(x);        int ry = Find(y);        if(rx != ry)            printf("-1\n");        else            printf("%d\n", abs(disx[x]-disx[y])+abs(disy[x]-disy[y]));    }    return 0;}


0 0
原创粉丝点击