BZOJ1018 [SHOI2008]堵塞的交通traffic(分块+并查集)

来源:互联网 发布:阿里云邮件服务器地址 编辑:程序博客网 时间:2024/04/28 00:02

这份题解没有在BZOJ上AC(狂汗不止),不过我觉得分块的思想挺不错的,就尝试了一下

不过相似的代码可以AC这道题LA 4082 Traffic Jam

如图,先给点编号,然后每一块中暴力维护并查集:


Open:在同一块中就维护并查集,在不同块互相连通就用一个link数组记录

Close:在同一块中就把块中元素的fa[]全部重新计算,在不同块中直接把link赋零

Ask:判断A及能到达的4个顶点,再递归4个顶点到其他块的顶点,看顶点与B是否连通


如果有哪位神犇能指点一下分块法如何能AC此题,或者想讨

论,欢迎随时与我交流^ ^

#include<stdio.h>#include<stdlib.h>#include<string.h>#define SIZE 512int G[200005][5]={0},p[200005]={0},fa[200005]={0},jiao[200005/SIZE+5][5],link[200005]={0},vis[200005]={0};int min(int a,int b){if(a<b) return a;return b;}int father(int x){if(fa[x]!=x) fa[x]=father(fa[x]);return fa[x];}int block(int x){return (x-1)/SIZE+1;}int cx(int a,int b){int i,x,BL=block(a);vis[a]=1;if(father(a)==father(b)) return 1;for(i=1;i<=4;i++)if(father(jiao[BL][i])==father(a)){vis[jiao[BL][i]]=1;x=link[jiao[BL][i]];if(x!=0&&vis[x]==0)if(cx(x,b)==1) return 1;}return 0;}int main(){char s[20]={0};int n,i,j,r,c,a,b,tou,wei,BL;scanf("%d",&n);n*=2;for(i=1;i<=n;i++)fa[i]=i;for(i=1;i<=(n-1)/SIZE+1;i++){jiao[i][1]=(i-1)*SIZE+1;jiao[i][2]=jiao[i][1]+1;jiao[i][4]=min(i*SIZE,n);jiao[i][3]=jiao[i][4]-1;}while(scanf("%s",s)){if(s[0]=='E') break;scanf("%d%d",&r,&c);a=2*(c-1)+r;scanf("%d%d",&r,&c);b=2*(c-1)+r;if(s[0]=='C')//关 {for(i=1;i<=p[a];i++)if(G[a][i]==b){G[a][i]=G[a][p[a]--];break;}for(i=1;i<=p[b];i++)if(G[b][i]==a){G[b][i]=G[b][p[b]--];break;}if(block(a)==block(b)){BL=block(a);tou=(BL-1)*SIZE+1;wei=min(BL*SIZE,n);for(i=tou;i<=wei;i++)fa[i]=i;for(i=tou;i<=wei;i++)for(j=1;j<=p[i];j++)if(block(G[i][j])==BL) fa[father(i)]=father(G[i][j]);}else link[a]=link[b]=0;}if(s[0]=='O')//开 {G[a][++p[a]]=b;G[b][++p[b]]=a;if(block(a)==block(b)) fa[father(a)]=father(b);else{link[a]=b;link[b]=a;}}if(s[0]=='A')//询问 {memset(vis,0,sizeof(vis));if(cx(a,b)==1) printf("Y\n");else printf("N\n");}}return 0;}


0 0
原创粉丝点击