[bzoj2574] [Poi1999]Store-Keeper

  坑啊。。

  膜了半天byvoid大爷的题解。https://www.byvoid.com/blog/poi-1999-mag/?replytocom=1335/

  一开始从人的位置bfs一波,看看能走到初始包裹哪些方向上。要注意不能穿过初始包裹...byvoid的标程在处理穿过包裹什么的地方有问题...但数据略弱。

  之后如题解所述。

  发现自己不会求点双连通分量QAQ。。那部分就抄标程了...

  大概就是记录一下当前走过的边,遇到割点就一直出栈...和求强连通分量差不多,就是一个点可能在多个点双里面..这个比较烦

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn=10023;
  7 const int xx[4]={-1,1,0,0},yy[4]={0,0,-1,1};
  8 struct zs{int too,pre;}e[maxn<<2];int tot,last[maxn];
  9 int too[2333333],pre[2333333],la[maxn],tt,st1[maxn],top,cnt,st2[maxn],uuu[103][103][4][4];bool uu[maxn];
 10 struct poi{int x,y;}S,T,M;
 11 struct zs1{int x,y,dir;}dl[maxn<<2];
 12 int dfn[maxn],low[maxn],tim;
 13 bool gd[maxn],u[maxn];
 14 int id[103][103],dis[103][103][4],q[maxn];
 15 char mp[103][103];
 16 int i,j,k,n,m,man,st,ed;
 17  
 18 inline void ins(int a,int b){
 19     int i=la[a];
 20     while(i&&too[i]!=b)i=pre[i];
 21     if(i)return;
 22     too[++tt]=b,pre[tt]=la[a],la[a]=tt;
 23 }
 24 inline bool same(int a,int b){
 25     int i;bool flag;
 26     for(i=la[a];i;i=pre[i])uu[too[i]]=1;
 27     for(i=la[b];i&&!uu[too[i]];i=pre[i]);
 28     flag=i!=0;
 29     for(i=la[a];i;i=pre[i])uu[too[i]]=0;
 30     return flag;
 31 }
 32 inline bool canget(int x,int y,int dir1,int dir2){
 33     if(!gd[id[x][y]])return 1;
 34     if(uuu[x][y][dir1][dir2]<0)
 35         return (uuu[x][y][dir1][dir2]=same( id[x+xx[dir1]][y+yy[dir1]] , id[x+xx[dir2]][y+yy[dir2]] ));
 36     else return uuu[x][y][dir1][dir2];
 37 }
 38 void tarjan(int x,int fa){
 39     dfn[x]=low[x]=++tim;int too,u,v;
 40     for(int i=last[x];i;i=e[i].pre)if(dfn[e[i].too]<dfn[x]){
 41         too=e[i].too;
 42         if(!dfn[too]){
 43             st1[++top]=x,st2[top]=too;
 44             tarjan(too,x),low[x]=min(low[x],low[too]);
 45             if(low[too]>=dfn[x]){
 46                 gd[x]=1;
 47                 cnt++;
 48                 do{
 49                     u=st1[top],v=st2[top],
 50                     ins(u,cnt),ins(v,cnt),top--;
 51                 }while((u!=x||v!=too)&&(u!=too||v!=x));
 52             }
 53         }
 54         else low[x]=min(low[x],dfn[e[i].too]);
 55     }
 56 }
 57  
 58 inline void insert(int a,int b){
 59     e[++tot].too=b,e[tot].pre=last[a],last[a]=tot,
 60     e[++tot].too=a,e[tot].pre=last[b],last[b]=tot;
 61 }
 62  
 63 inline bool check(int x,int y){return x>0&&y>0&&x<=n&&y<=m&&mp[x][y]!='S';}
 64  
 65 inline void bfs(int s){
 66     int l=0,r=1,i,now;q[1]=s,u[s]=1;
 67     while(l<r)
 68         for(i=last[now=q[++l]];i;i=e[i].pre)if(!u[e[i].too]&&e[i].too!=st)
 69             u[e[i].too]=1,q[++r]=e[i].too;
 70 }
 71 inline int run(){
 72     int l=0,r=0,i,nx,ny,ndir,ndis,x,y;
 73     for(i=0;i<4;i++){
 74         x=S.x+xx[i],y=S.y+yy[i];
 75         if(check(x,y)&&u[id[x][y]])dl[++r]=(zs1){S.x,S.y,i},dis[S.x][S.y][i]=1;//,printf("st:%d,%d\n",x,y);
 76     }
 77     while(l<r){
 78         l++,nx=dl[l].x,ny=dl[l].y,ndir=dl[l].dir,ndis=dis[nx][ny][ndir];
 79         x=nx+xx[ndir^1],y=ny+yy[ndir^1];//printf("case:%d,%d  dis:%d  dir:%d\n",nx,ny,ndis,ndir);
 80         if(!check(x,y))continue;
 81         if(x==T.x&&y==T.y)return ndis;
 82         for(i=0;i<4;i++)
 83             if(check(x+xx[i],y+yy[i])&&!dis[x][y][i]&&canget( x,y,ndir,i ))
 84                 dis[x][y][i]=ndis+1,dl[++r]=(zs1){x,y,i};
 85     }
 86     return -233;
 87 }
 88 int main(){
 89     memset(uuu,200,sizeof(uuu));
 90     scanf("%d%d",&n,&m);int tmp=0;tot=1;
 91     for(i=1;i<=n;i++){
 92         scanf("%s",mp[i]+1);
 93         for(j=1;j<=m;j++)if(mp[i][j]!='S'){
 94             id[i][j]=++tmp;
 95             for(k=0;k<4;k+=2){
 96                 int x=i+xx[k],y=j+yy[k];
 97                 if(check(x,y))
 98                     insert(id[i][j],id[x][y]);//,printf("(%d,%d)-->(%d,%d)\n",x,y,i,j);
 99             }
100             if(mp[i][j]=='M')man=tmp,M=(poi){i,j};
101             if(mp[i][j]=='P')st=tmp,S=(poi){i,j};
102             if(mp[i][j]=='K')ed=tmp,T=(poi){i,j};
103         }
104     }//return 233;
105     for(i=1;i<=tmp;i++)if(!dfn[i])tarjan(i,0);
106 //  for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(id[i][j]){
107 //      if(mp[i][j]!='S')printf("(%d,%d)  %d   fa:%d\n",i,j,id[i][j],getfa(id[i][j]));
108 //      if(gd[id[i][j]])printf("        gd:  (%d,%d)\n",i,j);
109 //  }
110     bfs(man);
111     int ans=run();
112     if(ans<0)puts("NO");else printf("%d\n",ans);
113 }
View Code

 

posted @ 2016-07-06 19:00  czllgzmzl  阅读(381)  评论(0编辑  收藏  举报