zoukankan      html  css  js  c++  java
  • BZOJ 3362 POJ 1984 Navigation Nightmare 并与正确集中检查

    标题效果:一些养殖场是由一些南北或东西向的道路互连。

    镶上在不断的过程中会问两个农场是什么曼哈顿的距离,假设现在是不是通信。那么输出-1。


    思维:并与正确集中检查,f[i]点i至father[i]距离,为了维持两个值,一个是东西向的距离。一个是南北向的距离,由于以后更新的时候要用到。在合并的时候有些特殊。如今有一条边(x->y),设fx为x的根。fy为y的根,那么如今知道f到fx的距离。y到fy的距离。还知道x到y的距离,设fx到fy的距离为dis,则dis + f[y] = f[x] + edge[p].w,那么dis = f[x] - f[y] + edge[p].w。

    依据这个公式来合并两个树就能够了。


    CODE:


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 40010
    using namespace std;
    
    struct Complex{
    	int x,y,len;
    	char c;
    }edge[MAX];
    struct Ask{
    	int x,y;
    	int pos,_id;
    	bool operator <(const Ask &a)const {
    		return pos < a.pos;
    	}
    }ask[MAX];
    struct Status{
    	int x,y;
    
    	Status(int _,int __):x(_),y(__) {}
    	Status() {}
    	Status operator +(const Status &a)const {
    		return Status(x + a.x,y + a.y);
    	}
    	Status operator -(const Status &a)const {
    		return Status(x - a.x,y - a.y);
    	}
    }f[MAX];
    
    int points,edges,asks;
    int father[MAX];
    int ans[MAX];
    
    char s[10];
    
    void Pretreatment();
    
    int Find(int x);
    
    int main()
    {
    	cin >> points >> edges;
    	Pretreatment();
    	for(int i = 1;i <= edges; ++i) {
    		scanf("%d%d%d%s",&edge[i].x,&edge[i].y,&edge[i].len,s);
    		edge[i].c = s[0];
    	}
    	cin >> asks;
    	for(int i = 1;i <= asks; ++i)
    		scanf("%d%d%d",&ask[i].x,&ask[i].y,&ask[i].pos),ask[i]._id = i;
    	sort(ask + 1,ask + asks + 1);
    	int now = 1;
    	for(int i = 1;i <= edges; ++i) {
    		int fx = Find(edge[i].x);
    		int fy = Find(edge[i].y);
    		if(fx != fy) {
    			father[fy] = fx;
    			Status temp;
    			if(edge[i].c == 'N')	temp = Status(0,edge[i].len);
    			if(edge[i].c == 'S')	temp = Status(0,-edge[i].len);
    			if(edge[i].c == 'E')	temp = Status(edge[i].len,0);
    			if(edge[i].c == 'W')	temp = Status(-edge[i].len,0);
    			f[fy] = f[edge[i].x] - f[edge[i].y] + temp;
    		}
    		while(i >= ask[now].pos && now <= asks) {
    			int fx = Find(ask[now].x);
    			int fy = Find(ask[now].y);
    			if(fx != fy)	ans[ask[now]._id] = -1;
    			else {
    				Status temp = f[ask[now].x] - f[ask[now].y];
    				ans[ask[now]._id] = abs(temp.x) + abs(temp.y);
    			}
    			++now;
    		}
    	}
    	for(int i = 1;i <= asks; ++i)
    		printf("%d
    ",ans[i]);
    	return 0;
    }
    
    void Pretreatment()
    {
    	for(int i = 1;i <= points; ++i)
    		father[i] = i;
    }
    
    int Find(int x)
    {
    	if(father[x] == x)	return x;
    	int temp = father[x];
    	father[x] = Find(father[x]);
    	f[x] = f[x] + f[temp];
    	return father[x];
    }


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    01
    商城管理系统
    10
    09
    08
    07(3)
    07(2)
    07
    06
    jsp第一次作业
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4712944.html
Copyright © 2011-2022 走看看