BZOJ 3362 POJ 1984 Navigation Nightmare 带权并查集

来源:互联网 发布:使命召唤ol自由数据 编辑:程序博客网 时间:2024/05/29 12:53

题目大意:一些农场由一些东西向或者南北向的路相互连接。在不断加边的过程中会询问两个农场的曼哈顿距离是多少,如果目前还不连通,那么输出-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 40010using 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\n",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];}


0 0
原创粉丝点击