标签:vertica const computer input [] enc pair most root
题目链接:http://poj.org/problem?id=1984
Time Limit: 2000MS Memory Limit: 30000K Case Time Limit: 1000MS
Description
F1 --- (13) ---- F6 --- (9) ----- F3
| |
(3) |
| (7)
F4 --- (20) -------- F2 |
| |
(2) F5
|
F7
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Each line contains four space-separated entities, F1,
F2, L, and D that describe a road. F1 and F2 are numbers of
two farms connected by a road, L is its length, and D is a
character that is either ‘N‘, ‘E‘, ‘S‘, or ‘W‘ giving the
direction of the road from F1 to F2.
* Line M+2: A single integer, K (1 <= K <= 10,000), the number of FB‘s
queries
* Lines M+3..M+K+2: Each line corresponds to a query from Farmer Bob
and contains three space-separated integers: F1, F2, and I. F1
and F2 are numbers of the two farms in the query and I is the
index (1 <= I <= M) in the data after which Bob asks the
query. Data index 1 is on line 2 of the input data, and so on.
Output
* Lines 1..K: One integer per line, the response to each of Bob‘s
queries. Each line should contain either a distance
measurement or -1, if it is impossible to determine the
appropriate distance.
Sample Input
7 6 1 6 13 E 6 3 9 E 3 5 7 S 4 1 3 N 2 4 20 W 4 7 2 S 3 1 6 1 1 4 3 2 6 6
Sample Output
13 -1 10
Hint
题意:
有n个节点,给出m条数据,每条数据包含F1,F2,L,D,代表从节点F1到F2的距离为L,D为‘E/W/S/N‘,代表了F1→F2是指向东/西/南/北;
现在又有个人来给出k条询问,每条询问包含F1,F2,IDX,代表了查询节点F1和F2之间的距离,本次查询发生在录入第IDX条数据之后(也就是说本次查询时,第IDX+1条往后的数据都还是未知的);
注意:对于查询的回答,必须按照查询输入的顺序进行输出;同时可能在读入第idx条数据之后,读入第idx+1条数据之前,会有多个查询。
题解:
并查集建树,par[x]代表x的父亲节点,val[x].X和val[x].Y分别代表par[x]->x向量的水平分量和竖直分量;
注意做好find()函数内val[x]的更新、unite两个节点时val[]更新,并且注意将答案按照查询的顺序输出即可。
AC代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int maxn=40000+10; int n,m,k; int par[maxn]; struct Val{ int X,Y; //par[x]->x向量的水平分量和竖直分量 }val[maxn]; void init(int l,int r){for(int i=l;i<=r;i++) par[i]=i,val[i].X=val[i].Y=0;} int find(int x) { if(par[x]==x) return x; else { int root=find(par[x]); val[x].X+=val[par[x]].X; val[x].Y+=val[par[x]].Y; return par[x]=root; } } struct Data{ int F1,F2,L; char D[3]; }data[maxn]; vector<int> D2Q[maxn]; //Data->Query struct Query{ int F1,F2; int id; //记录下是第id个查询 }query[maxn]; struct Res{ int val; //第id个查询的答案值 int id; //代表本结果是对应到第id个查询的 Res(int val,int id){this->val=val,this->id=id;} bool operator<(const Res &oth)const { return id<oth.id; } }; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d%s",&data[i].F1,&data[i].F2,&data[i].L,data[i].D); scanf("%d",&k); for(int i=1;i<=n;i++) D2Q[i].clear(); for(int i=1,idx;i<=k;i++) { scanf("%d%d%d",&query[i].F1,&query[i].F2,&idx); query[i].id=i; D2Q[idx].push_back(query[i].id); //记录一下第i个询问发生在第idx个数据之后 } init(1,n); vector<Res> res; for(int i=1,a,b,t1,t2;i<=m;i++) { a=data[i].F1, b=data[i].F2; t1=find(a), t2=find(b); if(t1!=t2) { par[t2]=t1; int dX,dY; //dX是a->b向量的水平分量,dY是a->b向量的竖直分量 if(data[i].D[0]==‘E‘) dX=data[i].L, dY=0; if(data[i].D[0]==‘W‘) dX=-data[i].L, dY=0; if(data[i].D[0]==‘N‘) dX=0, dY=data[i].L; if(data[i].D[0]==‘S‘) dX=0, dY=-data[i].L; val[t2].X=val[a].X+dX-val[b].X; val[t2].Y=val[a].Y+dY-val[b].Y; } //在录入本次数据之后,查看是否有查询,若有尝试进行回答 for(int j=0,_size=D2Q[i].size();j<_size;j++) { Query Q=query[D2Q[i][j]]; a=Q.F1, b=Q.F2; t1=find(a), t2=find(b); int ans; if(t1!=t2) ans=-1; else ans=abs(val[a].X-val[b].X)+abs(val[a].Y-val[b].Y); res.push_back(Res(ans,Q.id)); //将查询结果进行记录 } } sort(res.begin(),res.end()); //将查询的结果按照之前查询的顺序排列 for(int i=0;i<res.size();i++) printf("%d\n",res[i].val); }
POJ 1984 - Navigation Nightmare - [带权并查集]
标签:vertica const computer input [] enc pair most root
原文地址:https://www.cnblogs.com/dilthey/p/8955133.html