POJ 1984

我做过的最棘手的一道题了,不是因为难,难就是不懂,而是因为明明思路对了,却调了很久程序没发现自己哪错了。。。。。就连样例都不过

操,别人的代码::::::::::::::::::::::::::::...。。。

突然醒悟了,好像在坐标转换时错了。注意哦,坐标转换的方法。。。

坑了我一晚上。。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cctype>
#include <algorithm>
#define LL unsigned __int64
using namespace std; 

const int N=  40100;

int pre[N],rank[N];
struct Edge{
	int u,v,c;
	char dir;
}edge[N];
struct Quest{
	int u,v;
	int index,idp;
	bool operator <(const Quest &a)const{
		if(index<a.index) return true;
		return false;
	}
}qask[N/4];
struct Node{
	int dx,dy;
}node[N];
int ans[N];
int n,m,qk;

int findx(int x){
    int r=x;
    int tx=node[x].dx,ty=node[x].dy;
    while(pre[r]!=-1){
	    r=pre[r];
	    tx+=node[r].dx;
	    ty+=node[r].dy;
    }
    int dtx,dty,q;
    while(x!=r){
	    q=pre[x];
	    dtx=node[x].dx,dty=node[x].dy;
	    node[x].dx=tx,node[x].dy=ty;
	    pre[x]=r;
	    tx-=dtx,ty-=dty;
    	x=q;
    }
	return r;
}

void Union(int u,int v,int k){
	int uf=findx(u);
	int vf=findx(v);
	pre[uf]=vf;
	node[uf].dx=node[v].dx-node[u].dx;
	node[uf].dy=node[v].dy-node[u].dy;
	switch(edge[k].dir){
		case ‘N‘:node[uf].dy+=edge[k].c; break;
		case ‘S‘:node[uf].dy-=edge[k].c; break;
		case ‘W‘:node[uf].dx+=edge[k].c; break;
		case ‘E‘:node[uf].dx-=edge[k].c; break;
	}
}

void work(){
	int li=0,root1,root2;
	for(int i=0;i<qk;i++){
		for(int k=li;k<qask[i].index&&k<m;k++){
			Union(edge[k].u,edge[k].v,k);
		}
		root1=findx(qask[i].u);
		root2=findx(qask[i].v);
		if(root1!=root2){
			ans[qask[i].idp]=-1;
		}
		else {
			int a=abs(node[qask[i].u].dx-node[qask[i].v].dx);
			int b=abs(node[qask[i].u].dy-node[qask[i].v].dy);
			ans[qask[i].idp]=a+b;
		}
		li=qask[i].index;
	}
}

int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		for(int i=1;i<=n;i++){
			pre[i]=-1;
			node[i].dx=node[i].dy=0;
		}
		for(int i=0;i<m;i++){
			scanf("%d %d %d %c",&edge[i].u,&edge[i].v,&edge[i].c,&edge[i].dir);
		}
		scanf("%d",&qk);
		for(int i=0;i<qk;i++){
			scanf("%d%d%d",&qask[i].u,&qask[i].v,&qask[i].index);
			qask[i].idp=i;
		}
		sort(qask,qask+qk);
		work();
		for(int i=0;i<qk;i++)
		printf("%d\n",ans[i]);
	}
	return 0;
}

  

时间: 2024-08-09 02:31:08

POJ 1984的相关文章

POJ 1984 Navigation Nightmare 二维带权并查集

题目来源:POJ 1984 Navigation Nightmare 题意:给你一颗树 k次询问 求2点之间的曼哈顿距离 并且要在只有开始k条边的情况下 思路:按照方向 我是以左上角为根 左上角为原点 dx[i]为i点距离根的x坐标 dy[]是y坐标 这两个可以通过路径压缩求出 只不过是二维而已 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int m

POJ 1984 Navigation Nightmare (数据结构-并查集)

Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 4072   Accepted: 1615 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series o

【POJ 1984】Navigation Nightmare(带权并查集)

Navigation Nightmare Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series of M (1 <= M < 40,000) vertical and horizontal roads each of varying lengths (1 <= length <= 100

poj 1984 并查集

题目意思是一个图中,只有上下左右四个方向的边.给出这样的一些边, 求任意指定的2个节点之间的距离. 就是看不懂,怎么破 1 /* 2 POJ 1984 3 并查集 4 */ 5 6 #include <stdio.h> 7 #include <string.h> 8 #include <iostream> 9 #include <algorithm> 10 #include <math.h> 11 using namespace std; 12

poj 1984 Navigation Nightmare(带权并查集+小小的技巧)

题目链接:http://poj.org/problem?id=1984 题意:题目是说给你n个线,并告知其方向,然后对于后面有一些询问,每个询问有一个时间点,要求你输出在该时间点a,b的笛卡尔距离,如果不存在则输出-1 其实就是将权值分一下x,y,x表示x轴方向的权值,y表示y轴方向的权值.然后最后询问时稍微有点技巧 可以先记录一下每次询问的位置然后再按照时间点从小到大来排序最后这样就方便并查集了. #include <iostream> #include <cstring> #i

POJ 1984 - Navigation Nightmare - [带权并查集]

题目链接:http://poj.org/problem?id=1984 Time Limit: 2000MS Memory Limit: 30000K Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usually numbered/labeled 1..N. A series of M (1 <= M < 40,000)

POJ 1984 Navigation Nightmare 【经典带权并查集】

任意门:http://poj.org/problem?id=1984 Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7783   Accepted: 2801 Case Time Limit: 1000MS Description Farmer John's pastoral neighborhood has N farms (2 <= N <= 40,000), usuall

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] + ed

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