POJ1984

题目链接:https://vjudge.net/problem/POJ-1984

解题思路:并查集+离线操作。

  用dx[ ]和dy[ ]两个数组存储某点相对于该点所在集合的源头的方位,因此不难推知dx[ ]和dy[ ]要初始化为0。当把一个点依附到另一个点之上时所用的技巧值得细细体会。而finds( )函数则更是点睛之笔。

AC代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <queue>
 4 #include <cstring>
 5 #include <cmath>
 6 using namespace std;
 7 const int maxn=40000+10;
 8 int fa[maxn],dx[maxn],dy[maxn];
 9 struct input{
10     int F1,F2,L;
11     char D[3];
12 }inode[maxn];
13 struct query{
14     int F1,F2,I,ind;
15 }qnode[10005];
16 bool cmp(const query &a,const query &b){
17     return a.I<b.I;
18 }
19 int finds(int temp){
20     if(fa[temp]==-1)
21         return temp;
22     int tp=finds(fa[temp]);
23     dx[temp]+=dx[fa[temp]];
24     dy[temp]+=dy[fa[temp]];
25     return fa[temp]=tp;
26 }
27 int ans[10005];
28 int main(){
29     memset(fa,-1,sizeof(fa));
30     memset(dx,0,sizeof(dx));
31     memset(dy,0,sizeof(dy));
32     int N,M,K;
33     scanf("%d%d",&N,&M);
34     for(int i=0;i<M;i++)
35         scanf("%d%d%d%s",&inode[i].F1,&inode[i].F2,&inode[i].L,inode[i].D);
36     scanf("%d",&K);
37     for(int i=0;i<K;i++){
38         scanf("%d%d%d",&qnode[i].F1,&qnode[i].F2,&qnode[i].I);
39         qnode[i].ind=i;
40     }
41     sort(qnode,qnode+K,cmp);
42
43     int j=0;
44     for(int i=0;i<M;i++){
45         int t1=finds(inode[i].F1),t2=finds(inode[i].F2);
46         if(t1!=t2){
47             fa[t2]=t1;
48             if(inode[i].D[0]==‘N‘){
49                 dx[t2]=dx[inode[i].F1]-dx[inode[i].F2];
50                 dy[t2]=dy[inode[i].F1]-dy[inode[i].F2]+inode[i].L;
51             }
52             else if(inode[i].D[0]==‘E‘){
53                 dx[t2]=dx[inode[i].F1]-dx[inode[i].F2]+inode[i].L;
54                 dy[t2]=dy[inode[i].F1]-dy[inode[i].F2];
55             }
56             else if(inode[i].D[0]==‘W‘){
57                 dx[t2]=dx[inode[i].F1]-dx[inode[i].F2]-inode[i].L;
58                 dy[t2]=dy[inode[i].F1]-dy[inode[i].F2];
59             }
60             else if(inode[i].D[0]==‘S‘){
61                 dx[t2]=dx[inode[i].F1]-dx[inode[i].F2];
62                 dy[t2]=dy[inode[i].F1]-dy[inode[i].F2]-inode[i].L;
63             }
64         }
65         while(i==qnode[j].I-1){
66             int tt1=finds(qnode[j].F1),tt2=finds(qnode[j].F2);
67             if(tt1!=tt2)    ans[qnode[j].ind]=-1;
68             else
69                 ans[qnode[j].ind]=abs(dx[qnode[j].F1]-dx[qnode[j].F2])+abs(dy[qnode[j].F1]-dy[qnode[j].F2]);
70             j++;
71         }
72     }
73     for(int i=0;i<K;i++)    printf("%d\n",ans[i]);
74     return 0;
75 }

时间: 2024-10-11 02:02:45

POJ1984的相关文章

【poj1984】 Navigation Nightmare

http://poj.org/problem?id=1984 (题目链接) 题意 给出一棵树,这棵树是以平面直角坐标系为基准建立的,也就是每个节点最多只有上下左右4条边.现在动态建树,同时询问两点间的曼哈顿距离 Solution 一开始没看懂题,当做图写了个SPFA..后来发现是树于是删掉重新写了个DFS..最后又发现要动态建树..尼玛..又重新写了个带全并查集.. 注意询问并不保证时间是升序的,要按照给定询问顺序输出. 代码 // poj1984 #include<algorithm> #i

poj1984 带权并查集

题意:有多个点,在平面上位于坐标点上,给出一些关系,表示某个点在某个点的正东/西/南/北方向多少距离,然后给出一系列询问,表示在第几个关系给出后询问某两点的曼哈顿距离,或者未知则输出-1. 只要在元素的权值上保存两个信息,与祖先元素的两个方向的差,我选择正东和正北方向差(负值表示正西和正南),然后直接用带权并查集,询问时曼哈顿距离就是两个权值的绝对值之和.由于询问是嵌在给出关系中间的,所以要先存下所有关系和询问,离线做就行. 1 #include<stdio.h> 2 #include<

POJ1984 Navigation Nightmare

Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 6219   Accepted: 2230 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series of M (1 <= M < 4

poj1984 带权并查集(向量处理)

Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 5939   Accepted: 2102 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series o

POJ1984 Navigation Nightmare (hard?or!hard?)

DescriptionFarmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series of M (1 <= M < 40,000) vertical and horizontal roads each of varying lengths (1 <= length <= 1000) connect the farms.

并查集&amp;MST

[HDU] 1198 Farm Irrigation 基础最小生成树★ 1598 find the most comfortable road 枚举+最小生成树★★ 1811 Rank of Tetris 并查集+拓扑排序★★ 3926 Hand in Hand 同构图★ 3938 Portal 离线+并查集★★ 2489     Minimal Ratio Tree dfs枚举组合情况+最小生成树★ 4081     Qin Shi Huang's National Road System 最

【poj1985】 Cow Marathon

http://poj.org/problem?id=1985 (题目链接) 题意 求树上两点间最长距离.题目背景以及输入描述请见poj1984. Solution 树的直径. 代码 // poj1985 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define L

POJ1986 Distance Queries【最近公共祖先】【Tarjan-LCA算法】

Distance Queries Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 9777Accepted: 3425 Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He

POJ 1985 Cow Marathon【树的直径】

题目大意:给你一棵树,要你求树的直径的长度 思路:随便找个点bfs出最长的点,那个点一定是一条直径的起点,再从那个点BFS出最长点即可 以下研究了半天才敢交,1.这题的输入格式遵照poj1984,其实就是把后面的字母无视即可 2.这题数据量没给,所以把数组开得很大才敢交TUT #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <