bzoj3362[Usaco2004 Feb]Navigation Nightmare 导航噩梦
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3362
题目大意:
农夫约翰有N(2≤N≤40000)个农场,标号1到N,M(2≤M≤40000)条的不同的垂直或水
平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样,
![](http://www.lydsy.com/JudgeOnline/upload/201401/22(1).jpg)
图中农场用F1..F7表示, 每个农场最多能在东西南北四个方向连结4个不同的农场.此外,农场只处在道路的两端.道路不会交叉且每对农场间有且仅有一条路径.邻居鲍伯要约翰来导航,但约翰丢了农场的地图,他只得从电脑的备份中修复了.每一条道路的信息如下:
从农场23往南经距离10到达农场17
从农场1往东经距离7到达农场17
当约翰重新获得这些数据时,他有时被的鲍伯的问题打断:“农场1到农场23的曼哈顿距离是多少?”所谓在(XI,Yi)和(X2,y2)之间的“曼哈顿距离”,就是lxl - X21+lyl - y21.如果已经有足够的信息,约翰就会回答这样的问题(在上例中答案是17),否则他会诚恳地抱歉并回答-1.
题解:
带权并查集【没有学过啊QwQ
自己YY的方法是:开两个并查集,一种是水平的开个并差集,和竖直的开个并查集。结果发现有些点之前的关系可能是找不到的(在中间的话)。【<--正常的人都是应该看不懂的..
.说正解。。
就是在一个已知的数据块(额就是关系知道的)中,就取一个点来作中间(相关?)点,来当祖先
那么其他点记录的就是与祖先的相对位置(横纵坐标)。是位置,不是距离。距离可以询问的时候再用位置求。
东南西北四个方向就以相关点为原点假设个坐标系什么的,相对位置就加加减减。。。
合并的话,fy与fx的相对位置=x与fx的相对位置+y与x的相对位置-y与fy的相对位置。
p.s.看的Po姐博客,orz不会自定义类型的什么重载运算符啊。为什么要那样打QWQ
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; #define maxn 40100 //一个已知的数据块就取一个点来作中间(相关?)点 来当祖先 int fa[maxn],ans[maxn]; struct node//横纵坐标(就能算距离 { int x,y; node(){}//不能不打orz node(int a,int b):x(a),y(b){} node operator + (const node &b) const { return node(x+b.x,y+b.y); } node operator - (const node &b) const { return node(x-b.x,y-b.y); } }f[maxn]; struct pt{int x,y;node ds;}sr[maxn];//消息的两点x、y & 距离ds struct question{int x,y,t,id;}qs[maxn]; bool cmp(question x,question y) {return x.t<y.t;} int ffind(int x) { if (fa[x]!=x) { int y=fa[x]; fa[x]=ffind(fa[x]); f[x]=f[x]+f[y];//x到祖先的距离 }return fa[x]; } int dis(node x) {return abs(x.x)+abs(x.y);} int main() { //freopen("navigate.in","r",stdin); //freopen("navigate.out","w",stdout); int n,m,i,x,y,d,q,t;char c; scanf("%d%d",&n,&m); for (i=1;i<=n;i++) fa[i]=i,f[i]=node(0,0); for (i=1;i<=m;i++) { scanf("%d%d%d %c",&x,&y,&d,&c); sr[i].x=x,sr[i].y=y; if (c=='E') sr[i].ds=node(d,0); else if (c=='W') sr[i].ds=node(-d,0); else if (c=='N') sr[i].ds=node(0,d); else if (c=='S') sr[i].ds=node(0,-d); }scanf("%d",&q); for (i=1;i<=q;i++) { scanf("%d%d%d",&qs[i].x,&qs[i].y,&qs[i].t); qs[i].id=i; }sort(qs+1,qs+1+q,cmp); for (i=1,t=1;i<=q;i++) { for (;t<=qs[i].t;t++) { int fx=ffind(sr[t].x),fy=ffind(sr[t].y); fa[fy]=fx; f[fy]=f[sr[t].x]+sr[t].ds-f[sr[t].y]; } int fx=ffind(qs[i].x),fy=ffind(qs[i].y); if (fx!=fy) ans[qs[i].id]=-1; else ans[qs[i].id]=dis(f[qs[i].x]-f[qs[i].y]); } for (i=1;i<=q;i++) printf("%d\n",ans[i]); return 0; }