思路:记录每个点与其根结点的横向距离和纵向距离,当知道其父节点与根结点的关系,很容易推出当前节点与根结点的关系:
直接相加即可。
int p = a[x].par; a[x].dx += a[p].dx; a[x].dy += a[p].dy;
合并什么的就不多说了,很容易得出。
值得一说的就是需要按照合并节点的顺序把询问排序,最后按照询问的顺序再排一次序。
AC代码
#include <cstdio> #include <cmath> #include <cctype> #include <algorithm> #include <cstring> #include <utility> #include <string> #include <iostream> #include <map> #include <set> #include <vector> #include <queue> #include <stack> using namespace std; #pragma comment(linker, "/STACK:1024000000,1024000000") #define eps 1e-10 #define inf 0x3f3f3f3f #define PI pair<int, int> typedef long long LL; const int maxn = 40000 + 5; struct node{ int par; int dx, dy; }a[maxn]; struct Edge{ int u, v, dis, ch; }b[maxn]; struct Question{ int u, v, t, num; }q[10000+5]; void init(int n) { for(int i = 1; i <= n; ++i) { a[i].par = i; a[i].dx = a[i].dy = 0; } } int find(int x) { if(a[x].par == x) return x; int r = find(a[x].par); int p = a[x].par; a[x].dx += a[p].dx; a[x].dy += a[p].dy; return a[x].par = r; } void unionset(int x, int y, int dx, int dy) { int rx = find(x), ry = find(y); if(rx != ry) { a[rx].par = y; a[rx].dx = dx - a[x].dx; a[rx].dy = dy - a[x].dy; } } int get_dis(int x, int y) { int rx = find(x), ry = find(y); if(rx != ry) return -1; return abs(a[x].dx - a[y].dx) + abs(a[x].dy - a[y].dy); } bool cmp1(const Question &a, const Question &b) { return a.t < b.t; } bool cmp2(const PI &a, const PI &b) { return a.second < b.second; } int main() { int n, m, Q; while(scanf("%d%d", &n, &m) == 2) { init(n); for(int i = 1; i <= m; ++i) { scanf("%d %d %d %c", &b[i].u, &b[i].v, &b[i].dis, &b[i].ch); //printf("%d %d %d %c\n", b[i].u, b[i].v, b[i].dis, b[i].ch); } scanf("%d", &Q); for(int i = 1; i <= Q; ++i) { scanf("%d%d%d", &q[i].u, &q[i].v, &q[i].t); q[i].num = i; } vector<PI>ans; sort(q+1, q+Q+1, cmp1); int ind = 1; for(int i = 1; i <= m; ++i) { int dx, dy; switch(b[i].ch) { case 'E': dx = b[i].dis, dy = 0; break; case 'W': dx = -b[i].dis, dy = 0; break; case 'N': dx = 0, dy = b[i].dis; break; case 'S': dx = 0, dy = -b[i].dis; break; } unionset(b[i].u, b[i].v, dx, dy); while(ind <= Q && q[ind].t == i) { ans.push_back(make_pair(get_dis(q[ind].u, q[ind].v), q[ind].num)); ++ind; } } sort(ans.begin(), ans.end(), cmp2); for(int i = 0; i < ans.size(); ++i) printf("%d\n", ans[i].first); } return 0; }
如有不当之处欢迎指出!