I - Navigation Nightmare POJ - 1984
思路:
本题其实和普通的带权并查集一样。
- 无非是多加了一个维度(x方向和y方向,直接带权并查集基本操作)。
- merge和find时对两个disx和disy操作即可。
反思
- 字符读入时,不能这样!!!
因为会把空格读入,(除非:数字和字符是连在一起的)
AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
const int maxn=4e4+10;
int f[maxn];
int disx[maxn],disy[maxn];
int n,m,q;
struct point
{
int from,to;
int val;
char dic[10];//direction
}p[maxn];
int find(int x)
{
if(x==f[x])return x;
int root=find(f[x]);
disx[x]+=disx[f[x]];
disy[x]+=disy[f[x]];
return f[x]=root;
}
void merge(point p)
{
int op=0;
int a=p.from, b=p.to;
if(p.dic[0]=='S'||p.dic[0]=='E')op=1;
else op=-1;
// printf("%d %d %d %s\n\n",p.from,p.to,p.val,p.dic);
int uf=find(a);
int vf=find(b);
if(p.dic[0]=='S'||p.dic[0]=='N')
{
if(uf!=vf)
{
f[uf]=vf;
disx[uf]=disx[b]-disx[a]+p.val*op;
disy[uf]=disy[b]-disy[a];
}
}
else
{
if(uf!=vf)
{
f[uf]=vf;
disy[uf]=disy[b]-disy[a]+p.val*op;
disx[uf]=disx[b]-disx[a];
}
}
//printf("%d %d\n\n", disx[uf],disy[uf]);
}
int main()
{
scanf("%d%d", &n,&m);
For(i,1,n)f[i]=i;
For(i,1,m)scanf("%d%d%d%s",&p[i].from,&p[i].to,&p[i].val,&p[i].dic);
//cout<<"ok"<<endl;
scanf("%d", &q);
int now=1;
For(i,1,q)
{
int a,b,cur;
scanf("%d%d%d",&a,&b, &cur);
while(now<=cur)merge(p[now++]);
//for(int j=now+1; j<=cur&&j<=m; j++)merge(p[j]);
int A=find(a),B=find(b);
//printf("%d %d\n\n", disx[A],disy[A]);
//printf("%d %d\n\n", disx[a],disy[a]);
//printf("%d %d\n\n", disx[B],disy[B]);
//printf("%d %d\n\n", disx[b],disy[b]);
if(A!=B)printf("-1\n");
else
{
int tmp=abs(disx[a]-disx[b])+abs(disy[a]-disy[b]);
printf("%d\n",tmp);
}
}
return 0;
}