poj1984 带权并查集

题意:有多个点,在平面上位于坐标点上,给出一些关系,表示某个点在某个点的正东/西/南/北方向多少距离,然后给出一系列询问,表示在第几个关系给出后询问某两点的曼哈顿距离,或者未知则输出-1。

只要在元素的权值上保存两个信息,与祖先元素的两个方向的差,我选择正东和正北方向差(负值表示正西和正南),然后直接用带权并查集,询问时曼哈顿距离就是两个权值的绝对值之和。由于询问是嵌在给出关系中间的,所以要先存下所有关系和询问,离线做就行。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxm=4e4+10;
 6
 7 int fa[maxm],north[maxm],east[maxm];
 8 int a[maxm],b[maxm],l[maxm],ans[10005];
 9 char s[maxm][3];
10 struct que{
11     int num,a,b,t;
12     bool operator < (const que a)const{
13         return t<a.t;
14     }
15 }q[10005];
16
17 int abs(int a){return a>0?a:-a;}
18
19 void init(int n){
20     for(int i=1;i<=n;++i){
21         fa[i]=i;
22         north[i]=east[i]=0;
23     }
24 }
25
26 int find(int x){
27     int r=x,t1,t2,t3,cn=0,ce=0;
28     while(r!=fa[r]){
29         cn+=north[r];
30         ce+=east[r];
31         r=fa[r];
32     }
33     while(x!=r){
34         t1=fa[x];
35         t2=cn-north[x];
36         t3=ce-east[x];
37         north[x]=cn;
38         east[x]=ce;
39         fa[x]=r;
40         cn=t2;
41         ce=t3;
42         x=t1;
43     }
44     return r;
45 }
46
47 int main(){
48     int n,m;
49     scanf("%d%d",&n,&m);
50     init(n);
51     for(int i=1;i<=m;++i)scanf("%d%d%d%s",&a[i],&b[i],&l[i],s[i]);
52     int k;
53     scanf("%d",&k);
54     for(int i=1;i<=k;++i){
55         scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].t);
56         q[i].num=i;
57     }
58     sort(q+1,q+k+1);
59     int pos=1;
60     for(int i=1;i<=m;++i){
61         int x=find(a[i]),y=find(b[i]);
62         int Cn=0,Ce=0;
63         if(s[i][0]==‘N‘)Cn=l[i];
64         else if(s[i][0]==‘S‘)Cn=-l[i];
65         else if(s[i][0]==‘E‘)Ce=l[i];
66         else if(s[i][0]==‘W‘)Ce=-l[i];
67         if(x!=y){
68             fa[x]=y;
69             north[x]=north[b[i]]+Cn-north[a[i]];
70             east[x]=east[b[i]]+Ce-east[a[i]];
71         }
72
73         while(q[pos].t==i&&pos<=k){
74             x=find(q[pos].a);
75             y=find(q[pos].b);
76             if(x!=y)ans[q[pos].num]=-1;
77             else ans[q[pos].num]=abs(north[q[pos].a]-north[q[pos].b])+abs(east[q[pos].a]-east[q[pos].b]);
78             pos++;
79         }
80     }
81     for(int i=1;i<=k;++i)printf("%d\n",ans[i]);
82     return 0;
83 }

时间: 2024-10-11 17:23:30

poj1984 带权并查集的相关文章

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

hdu3038(带权并查集)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的); 思路: 很显然带权并查集咯,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离; 可以用rank[x]表示x到其父亲节点的距离,  将正确的距离关系合并到并查集中

【POJ1182】 食物链 (带权并查集)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之

【poj 1988】Cube Stacking(图论--带权并查集 模版题)

题意:有N个方块,M个操作{“C x”:查询方块x上的方块数:“M x y”:移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法:带权并查集.每堆方块作为一个集合,维护3个数组:fa[x]表示x方块所在堆的最顶部的方块:d[x]表示x方块所在堆的最底部的方块:f[x]表示x方块方块x上的方块数. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<

并查集练习2(带权并查集)

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~ poj1703 Find them, Catch them (带权并查集) 1 #include<cstdio> 2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 } 10 } 11 int fin(int x){ 12 i

Lightoj1009 Back to Underworld(带权并查集)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Back to Underworld Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Description The Vampires and Lykans are fighting each other to death. The war has become so fierc

[NOIP摸你赛]Hzwer的陨石(带权并查集)

题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域的陨石全搬到了另外一些区域. 在ndsf愉快的搬运过程中,Hzwer想知道一些陨石的信息.对于Hzwer询问的每个陨石i,你必须告诉他,在当前这个时候,i号陨石在所在区域x.x区域共有的陨石数y.以及i号陨石被搬运的次数z. 输入描述: 输入的第一行是一个正整数T.表示有多少组输入数据. 接下来共有

hdu 1558 Segment set【基础带权并查集+计算几何】

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3599    Accepted Submission(s): 1346 Problem Description A segment and all segments which are connected with it compose a segment set

Corporative Network(带权并查集)

这个题的题意是  当输入'E'是查找操作,查找从后面这个数到他的父亲这边的值,'I'代表把后面的数作为前面数的父亲 然后他们两个的差值代表这两个边的权值 水水的题 #include <stdio.h> #include <string.h> int par[20005]; int rank1[20005]; int abs(int hh) { return (hh>0)?hh:-hh; } void init() { for(int i=0;i<20005;i++) {