poj 1984(带权并查集)

题目链接:http://poj.org/problem?id=1984

 

题意:输入N表示村庄,M表示命令条数。接下来有M条命令,输入x,y,z,e

分别表示村庄x到村庄y的距离为z,e表示东西南北的方向。

接下来输入k,表示有k个询问。输入k行命令,分别有x,y,z。

求村庄x与村庄y在第z条命令后的曼哈顿距离。

 

经典的带权并查集的向量转移操作。

关键是要离线操作。

emmm,刚开始的时候方向搞错了。用自己的代码a题就是爽。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int maxn=40006;
  6 int fa[maxn],north[maxn],east[maxn];
  7 int ans[maxn];
  8 struct node{
  9     int a,b,c,d;
 10 }seek[maxn];
 11 struct edge{
 12     int id,x,y,z;
 13 }innum[maxn];
 14 bool cmp(edge a, edge b)
 15 {
 16     return a.z<b.z;
 17 }
 18 void init()
 19 {
 20     for(int i=0;i<maxn;i++){
 21         fa[i]=i;
 22         north[i]=0;
 23         east[i]=0;
 24     }
 25 }
 26 int find_fa(int x)
 27 {
 28     if(fa[x]==x) return x;
 29     int tmp=fa[x];
 30     fa[x]=find_fa(tmp);
 31     north[x]=north[x]+north[tmp];
 32     east[x]=east[x]+east[tmp];
 33     return fa[x];
 34 }
 35 int sqrt(int x)
 36 {
 37     if(x<0) return -x;
 38     return x;
 39 }
 40 
 41 int main()
 42 {
 43     int n,m;
 44     while( ~scanf("%d%d",&n,&m)){
 45         init();
 46         for(int i=1;i<=m;i++){
 47             char str[10];
 48             scanf("%d%d%d%s",&seek[i].a,&seek[i].b,&seek[i].c,str);
 49             if(str[0]=='E') seek[i].d=0;
 50             if(str[0]=='N') seek[i].d=1;
 51             if(str[0]=='W') seek[i].d=2;
 52             if(str[0]=='S') seek[i].d=3;
 53         }
 54         int k;
 55         scanf("%d",&k);
 56         for(int i=1;i<=k;i++){
 57             scanf("%d%d%d",&innum[i].x,&innum[i].y,&innum[i].z);
 58             innum[i].id=i;
 59         }
 60         sort( innum+1, innum+1+k, cmp);
 61         int now=1;
 62         for(int i=1;i<=k;i++){
 63             while(now<=innum[i].z){
 64                 int iop,kop,tmp,dic;
 65                 iop=seek[now].a;
 66                 kop=seek[now].b;
 67                 tmp=seek[now].c;
 68                 dic=seek[now].d;
 69                 int roota=find_fa(iop);
 70                 int rootb=find_fa(kop);
 71                 if(roota!=rootb){
 72                     fa[rootb]=roota;
 73                     if(dic==0){
 74                         east[rootb]=east[iop]-east[kop]+tmp;
 75                         north[rootb]=north[iop]-north[kop];
 76                     } else if(dic==1){
 77                         east[rootb]=east[iop]-east[kop];
 78                         north[rootb]=north[iop]-north[kop]+tmp;
 79                     } else if(dic==2){
 80                         east[rootb]=east[iop]-east[kop]-tmp;
 81                         north[rootb]=north[iop]-north[kop];
 82                     } else if(dic==3){
 83                         east[rootb]=east[iop]-east[kop];
 84                         north[rootb]=north[iop]-north[kop]-tmp;
 85                     }
 86                 }
 87                 now++;
 88             }
 89             int iop,kop;
 90             iop=innum[i].x; kop=innum[i].y;
 91             int roota=find_fa(iop);
 92             int rootb=find_fa(kop);
 93             if(roota!=rootb){
 94                 ans[innum[i].id]=-1;
 95             } else{
 96                 int x1,y1;
 97                 x1=sqrt(north[iop]-north[kop]);
 98                 y1=sqrt(east[iop]-east[kop]);
 99                 ans[innum[i].id]=x1+y1;
100             }
101         }
102 
103         for(int i=1;i<=k;i++){
104             printf("%d\n",ans[i]);
105         }
106     }
107     return 0;
108 }

 

posted @ 2018-05-30 20:45  flyer_duck  阅读(194)  评论(0编辑  收藏  举报