题意:n个地点,现在建设m条南北方向或东西方向的路,这些路是无向的,但是给出的路的信息是这种形式:1 3 15 E,表示从第1个点向东行驶15个距离会到达第3个点。现在有一些这种形式的询问:1 6 2,在建造完第2条路后,1和6的曼哈顿距离是多少。
题解:带权并查集
1.带权并查集模板题。
2.权值是点与点之间的横纵坐标距离。
3.注意:相对距离是相加的,而不是相减的,例如2和1的横坐标距离为-10,3和2的横坐标距离相差-20,那么可知3和1的横坐标距离相差(-20)+(-10)=-30,而不是(-20)-(-10)=-10,画一画图就知道了。
4.注意:合并根节点时需要画图思考细节。
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#define N 40005
using namespace std ;
int n , m , k ;
struct Edge
{
int u , v , len ;
char dir[5] ;
} edge[N] ;
struct Query
{
int f1 , f2 , index , mark , ans ;
} query[N] ;
struct Node
{
int pre ;
int x , y ;
} node[N] ;
bool cmp1(Query a , Query b)
{
return a.index < b.index ;
}
bool cmp2(Query a , Query b)
{
return a.mark < b.mark ;
}
int find(int x)
{
int temp = node[x].pre ;
if(x != temp)
{
node[x].pre = find(node[x].pre) ;
node[x].x += node[temp].x ;
node[x].y += node[temp].y ;
}
return node[x].pre ;
}
void join(int x)
{
int u , v ;
int ru , rv ;
int disx = 0 , disy = 0 ;
u = edge[x].u , v = edge[x].v ;
ru = find(u) ;
rv = find(v) ;
if(edge[x].dir[0] == 'E')
disx = edge[x].len ;
else if(edge[x].dir[0] == 'W')
disx = -edge[x].len ;
else if(edge[x].dir[0] == 'N')
disy = edge[x].len ;
else if(edge[x].dir[0] == 'S')
disy = -edge[x].len ;
if(ru != rv)
{
node[ru].pre = rv ;
node[ru].x = node[v].x - node[u].x - disx ;
node[ru].y = node[v].y - node[u].y - disy ;
}
}
int main()
{
int i , j ;
int update ;
int u , v ;
scanf("%d%d" , &n , &m) ;
for(i = 1 ; i <= m ; i ++)
scanf("%d%d%d%s" , &edge[i].u , &edge[i].v , &edge[i].len , &edge[i].dir) ;
scanf("%d" , &k) ;
for(i = 1 ; i <= k ; i ++)
{
scanf("%d%d%d" , &query[i].f1 , &query[i].f2 , &query[i].index) ;
query[i].mark = i ;
query[i].ans = -1 ;
}
for(i = 1 ; i <= n ; i ++)
{
node[i].pre = i ;
node[i].x = 0 ;
node[i].y = 0 ;
}
sort(query + 1 , query + k + 1 , cmp1) ;
update = 0 ;
for(i = 1 ; i <= k ; i ++)
{
while(update < query[i].index)
{
update ++ ;
join(update) ;
}
u = query[i].f1 , v = query[i].f2 ;
if(find(u) == find(v))
query[i].ans = abs(node[u].x - node[v].x) + abs(node[u].y - node[v].y) ;
}
sort(query + 1 , query + k + 1 , cmp2) ;
for(i = 1 ; i <= k ; i ++)
printf("%d\n" , query[i].ans) ;
}