【poj 1984】&【bzoj 3362】Navigation Nightmare(图论--带权并查集)

题意:平面上给出N个点,知道M个关于点X在点Y的正东/西/南/北方向的距离。问在刚给出一定关系之后其中2点的曼哈顿距离((x1,y1)与(x2,y2):l x1-x2 l+l y1-y2 l),未知则输出-1。

解法:带权并查集。sx[x]表示x与其根结点的横坐标的差,sy[x]表示x与其根结点的纵坐标的差。}
输入需要好好处理一下:1.我自定义(x,y,E)的x,y之间的横坐标差为正,W为负,N时的纵坐标差为正,S时为负;2.需要给询问排序,再一个个将关系存储下来。

注意——我将x,y合并联盟时的关系式就偷懒按 【poj 1182】食物链(图论--带权并查集) 所提到的用方块图直接推,发现样例对了,还1A了,速度也比较快!(我代码也算是很清晰的吧)❀(๑╯◡╰๑)❀ 所以我真的向神犇求解啊!!

P.S.我碰运气地没有完全推导、不负责任地打了ins( )里的式子,而对于这个hyc有另外的一种简单易懂的坐法:出现fx,x,fy,y,可知把fy附到x所在联盟下时,可以把 fy 和 y 颠倒相对位置,让输入的对于 x 和 y 的距离 d 可以直截了当地得到利用,赋值给“一身轻”的 y。

1 int fy=ffind(y);
2 sx[fy]=-sx[y],sy[fy]=-sy[y]; fa[fy]=y, fa[y]=x; 
3 sx[y]=w[t][0]*d,sy[y]=w[t][0]*d;

下面是我的完整代码——

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<iostream>
 6 using namespace std;
 7 
 8 const int N=40010,M=40010,K=10010;
 9 struct quiry{int x,y,t,id;}q[K];
10 struct node{int x,y,d,t;}a[M];
11 int n,m,k;
12 char s[3];
13 int fa[N],sx[N],sy[N],ans[K];
14 int w[5][2]={{1,0},{0,-1},{-1,0},{0,1}};//ESWN,multi
15 
16 bool cmp(quiry x,quiry y) {return x.t<y.t;}
17 int mabs(int x) {return x>0?x:-x;}
18 int ffind(int x)
19 {
20     if (fa[x]!=x)
21     {
22       int fx=fa[x];
23       fa[x]=ffind(fx);
24       sx[x]+=sx[fx];
25       sy[x]+=sy[fx];
26     }
27     return fa[x];
28 }
29 void ins(int x,int y,int d,int t)
30 {
31     int fx=ffind(x),fy=ffind(y);
32     if (fx==fy) return;
33     fa[fy]=fx;
34     sx[fy]=w[t][0]*d+sx[x]-sx[y];//
35     sy[fy]=w[t][1]*d+sy[x]-sy[y];//
36 }
37 int solve(int x,int y)
38 {
39     int fx=ffind(x),fy=ffind(y);
40     if (fx!=fy) return -1;
41     return mabs(sx[x]-sx[y])+mabs(sy[x]-sy[y]);
42 }
43 int main()
44 {
45     scanf("%d%d",&n,&m);
46     for (int i=1;i<=m;i++)
47     {
48       scanf("%d%d%d%s",&a[i].x,&a[i].y,&a[i].d,s);
49       if (s[0]=='E') a[i].t=0;
50       if (s[0]=='S') a[i].t=1;
51       if (s[0]=='W') a[i].t=2;
52       if (s[0]=='N') a[i].t=3;
53     }
54     scanf("%d",&k);
55     for (int i=1;i<=k;i++)
56     {
57       scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].t);
58       q[i].id=i;
59     }
60     sort(q+1,q+1+k,cmp);
61     for (int i=1;i<=n;i++) fa[i]=i,sx[i]=sy[i]=0;
62     int t=0;
63     for (int i=1;i<=k;i++)
64     {
65       while (t<q[i].t && t<m) {t++; ins(a[t].x,a[t].y,a[t].d,a[t].t);}
66       ans[q[i].id]=solve(q[i].x,q[i].y);
67     }
68     for (int i=1;i<=k;i++) printf("%d
",ans[i]);
69     return 0;
70 }
原文地址:https://www.cnblogs.com/konjak/p/6030978.html