并查集经典题之POJ1984

题意:依据n个Famr之间有限的连接关系,求解指定两个Farm之间的Manhattan distance

分析:

1.k个Query依据时间点的顺序输入

2.对于输入的每一个连接关系,动态更新合并树的相对坐标。

//Date:     2015.04.21
//Time:     125ms
//Memory:   1564k

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX=40005;
int sum[MAX];
int n,m,k;

struct Farm{
    int x,y,tree,next;
}farms[MAX];

struct Information{
    int f1,f2,dx,dy;
}data[MAX];

void Update(int t1,int t2,int dx,int dy){
    int i=t2,p;
    while(~i){
       farms[i].tree=t1;
       farms[i].x += dx;
       farms[i].y += dy;
       p=i;i=farms[i].next;
    }
    farms[p].next=farms[t1].next;
    farms[t1].next=t2;
    sum[t1]=sum[t1]+sum[t2]+1;
}
void init(){
    memset(data,0,sizeof(data));
    memset(sum,0,sizeof(sum));
    memset(farms,0,sizeof(farms));
    for(int i=1;i<=n;i++){
       farms[i].tree=i;
       farms[i].next=-1;
    }
}
int main(){
    int i,j,t,len,f1,f2,t1,t2;
    char dir;

    scanf("%d%d",&n,&m);
    init();
    for(i=0;i<m;i++){
        scanf("%d %d %d %c",&data[i].f1,&data[i].f2,&len,&dir);
        switch(dir){
            case 'E':data[i].dx= len;break;
            case 'S':data[i].dy=-len;break;
            case 'W':data[i].dx=-len;break;
            case 'N':data[i].dy= len;break;
        }
    }
    scanf("%d",&k);
    for(j=i=0;i<k;i++){
        scanf("%d %d %d",&f1,&f2,&t);
        for(;j<t;j++){
            t1=farms[data[j].f1].tree;t2=farms[data[j].f2].tree;
            if(sum[t1]>=sum[t2])
                Update(t1,t2,farms[data[j].f1].x+data[j].dx-farms[data[j].f2].x,farms[data[j].f1].y+data[j].dy-farms[data[j].f2].y);
            else
                Update(t2,t1,farms[data[j].f2].x-data[j].dx-farms[data[j].f1].x,farms[data[j].f2].y-data[j].dy-farms[data[j].f1].y);
        }
        t1=farms[f1].tree;t2=farms[f2].tree;
        if(t1!=t2)
            printf("-1\n");
        else
            printf("%d\n",abs(farms[f1].x-farms[f2].x)+abs(farms[f1].y-farms[f2].y));
    }
    return 0;
}

你可能感兴趣的:(并查集经典题之POJ1984)