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;
}

原文地址:https://www.cnblogs.com/lvpengms/p/1717463.html