poj1984并查集的相对偏移

#include<stdio.h>//典型题
#include<math.h>
#define N 40010
struct node {
int x,y,z;
}pre[N];
struct fff{
int a,b,dis;
char s[2];
}map[N];//储存
int find(int x) {
if(x!=pre[x].z)  {
int h=pre[x].z;
pre[x].z=find(pre[x].z);
   pre[x].x=pre[x].x+pre[h].x;//路径压缩
pre[x].y=pre[x].y+pre[h].y;//
}
return pre[x].z;
}
void insert(int a,int b,int x,int y){
int f1=find(a);
int f2=find(b);
if(f1==f2)return ;
pre[f1].z=f2;
pre[f1].x=pre[b].x-pre[a].x-x;//原来b以a为参考,a以其根root1为参考,b以其根root2为参考。现在root1以a为参考,a以b为参考,b还是以root2为参考
pre[f1].y=pre[b].y-pre[a].y-y;//a-pre[a]-root,b-xy-a,b-pre[b]-root2.变为root1-负pre[a]-a,a-负xy-b,b-pre[b]-root2。故root1-负pre[a]+负xy+pre[b]-root2.其中pre[a],pre[b],
                              //代表其相当于a,b的坐标,xy相当于坐标法

}
int main() {
int n,m,i,j,k,a,b,c,x,y,f1,f2,len;
char ch;
while(scanf("%d%d",&n,&m)!=EOF) {
for(i=1;i<=m;i++) 
scanf("%d%d%d%s",&map[i].a,&map[i].b,&map[i].dis,map[i].s);
for(i=1;i<=n;i++) {
pre[i].z=i;
pre[i].x=pre[i].y=0;//初始化
}
scanf("%d",&k);
j=1;
while(k--) {
scanf("%d%d%d",&a,&b,&c);
for(i=j;i<=c;i++) {
ch=map[i].s[0];x=0;y=0;
if(ch=='N') x=map[i].dis;
if(ch=='E') y=map[i].dis;//以N,E为正方向
if(ch=='S') x=-map[i].dis;
if(ch=='W') y=-map[i].dis;
insert(map[i].a,map[i].b,x,y);
}
f1=find(a);
f2=find(b);
if(f1!=f2)//是否有同一根节点
printf("-1\n");
else {
len=abs(pre[a].x-pre[b].x)+abs(pre[a].y-pre[b].y);//曼哈顿距离
printf("%d\n",len);
}
j=c+1;//
}

}
return 0;
}
posted @ 2013-11-25 16:09  HYDhyd  阅读(181)  评论(0编辑  收藏  举报