• 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.这些农场的分布就像下面的地图一样,
    图中农场用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
    ",ans[i]);
    	return 0;
    }



  • 相关阅读:
    C C++ 数字后面加 LL是什么意思
    stdio.h cstdio的区别
    printf scanf cin cout的区别与特征
    PAT Basic 1020
    PAT Basic 1012
    PAT Basic 1046
    PAT Basic 1026
    PAT Basic 1011
    PAT Basic 1016
    PAT Basic 1009
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527839.html
Copyright © 2020-2023  润新知