POJ 1984 Navigation Nightmare (并查集)
题意:给定一组线段和方向,然后查询点的距离。
思路:并查集的基本操作,在记录坐标偏移的时候注意一下,两个点之间和他们的根之间的坐标偏移关系可以用关系式表达出来,只要在纸上写一写就ok。查询输入的时候还是按ind排下序在处理线段。
/*
* 简单题 并查集的使用,就当是复习了。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
using namespace std;
const int BORDER = (1<<20)-1;
const int MAXSIZE = 37;
const int MAXN = 40005;
const int INF = 1000000000;
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) x=((x+1)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
typedef struct{
int x,y;
}Node;
typedef struct{
int a,b;
int x,y;
}Road;
typedef struct{
int a,b;
int ind;
}Ask;
bool cmp(const Ask& a,const Ask& b)
{
return a.ind < b.ind;
}
Node node[MAXN];
Road road[MAXN*1000];
Ask qus[MAXN*10];
int n,m,k;
int pre[MAXN];
int init()
{
for(int i = 0; i < MAXN; ++i)
node[i].x = node[i].y = 0;
CLR(pre,-1);
return 0;
}
int find_set(int x)
{
int root = x;
int c_px,c_py,p_py,p_px;
int tmp = 0;
p_px = node[x].x;
p_py = node[x].y;
while(pre[root] >= 0)
{
root = pre[root];
node[x].x += node[root].x;
node[x].y += node[root].y;
}
while( x != root)
{
tmp = pre[x];
c_px = p_px;
c_py = p_py;
p_px = node[tmp].x;
p_py = node[tmp].y;
node[tmp].x = node[x].x - c_px;
node[tmp].y = node[x].y - c_py;
pre[x] = root;
x = tmp;
}
return root;
}
void union_set(const int& root1,const int& root2,
const int& x,const int& y)
{
pre[root2] += pre[root1];
pre[root1] = root2;
node[root1].x = x;
node[root1].y = y;
return ;
}
void print()
{
for(int i = 1; i <= n; ++i)
printf("(%d,%d) ",node[i].x,node[i].y);
printf("%\n");
}
int input()
{
int root1,root2,x,y,i,j,a,b,len;
char c;
for(i = 0; i < m; ++i)
{
scanf("%d %d %d %c",&road[i].a,&road[i].b,&len,&c);
x = y = 0;
if(c=='N')
y = len;
else if(c=='S')
y = -len;
else if(c=='W')
x = -len;
else
x = len;
road[i].x = x;
road[i].y = y;
}
IN(k);
for(i = 0; i < k; ++i)
scanf("%d%d%d",&qus[i].a,&qus[i].b,&qus[i].ind);
return 0;
}
int work()
{
int i,j,tmp,root1,root2,ans,a,b,t,x,y;
int pre = 0;
sort(qus,qus+k,cmp);
for(i = 0; i < k; ++i)
{
a = qus[i].a;
b = qus[i].b;
t = qus[i].ind;
for(; pre < t; ++pre)
{
root1 = find_set(road[pre].a);
root2 = find_set(road[pre].b);
if(root1 == root2)
continue;
x = road[pre].x - node[road[pre].a].x + node[road[pre].b].x;
y = road[pre].y - node[road[pre].a].y + node[road[pre].b].y;
union_set(root1,root2,x,y);
}
root1 = find_set(a);
root2 = find_set(b);
ans = -1;
if(root1 != root2)
OUT(ans);
else
{
root1 = ABS(node[a].x-node[b].x);
root2 = ABS(node[a].y-node[b].y);
ans = root1 + root2;
OUT(ans);
}
}
return 0;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
input();
work();
}
return 0;
}