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 }