【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\n",ans[i]); 69 return 0; 70 }