• BZOJ4242 : 水壶


    对于任意两个建筑物,以它们之间的最短路为边权求出最小生成树。

    则询问(x,y)的答案为最小生成树上x到y路径上边权的最大值。

    BFS求出离每个点最近的建筑物以及到它的距离,可以发现只有交界处的边才有用,用这些边求MST即可。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int L=2010,N=200010,K=17,inf=~0U>>1;
    int H,W,n,m,Q,i,j,x,y,z,p,mx;
    int dis[L][L][2],q[L*L][2],h=1,t;
    int fa[N],g[N],v[N<<1],w[N<<1],nxt[N<<1],ed,f[N][K+1],fm[N][K+1],d[N];
    char s[L];bool a[L][L],vis[L][L];
    struct E{int x,y;E*nxt;}*e[L*L],pool[L*L],*cur=pool;
    inline void up(int&a,int b){if(a<b)a=b;}
    inline void bfs(int x,int y,int z,int p){
      if(x<1||x>H||y<1||y>W||vis[x][y]||!a[x][y])return;
      vis[x][y]=1,dis[x][y][0]=z,dis[x][y][1]=p,q[++t][0]=x,q[t][1]=y;
    }
    inline void check(int a,int b,int c,int d){
      if(vis[a][b]&&vis[c][d]&&dis[a][b][1]!=dis[c][d][1]){
        int x=dis[a][b][0]+dis[c][d][0];
        E*p=cur++;p->x=dis[a][b][1];p->y=dis[c][d][1];p->nxt=e[x];e[x]=p;
        up(mx,x);
      }
    }
    int F(int x){return fa[x]==x?x:fa[x]=F(fa[x]);}
    inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    void dfs(int x,int pre,int dis){
      f[x][0]=pre,fm[x][0]=dis;d[x]=d[pre]+1;
      for(int i=1;i<=K;i++)f[x][i]=f[f[x][i-1]][i-1],fm[x][i]=max(fm[x][i-1],fm[f[x][i-1]][i-1]);
      for(int i=g[x];i;i=nxt[i])if(v[i]!=pre)dfs(v[i],x,w[i]);
    }
    inline int ask(int x,int y){
      if(F(x)!=F(y))return -1;
      int t=0,i;
      if(d[x]<d[y])swap(x,y);
      for(i=K;~i;i--)if(d[f[x][i]]>=d[y])up(t,fm[x][i]),x=f[x][i];
      if(x==y)return t;
      for(i=K;~i;i--)if(f[x][i]!=f[y][i])up(t,max(fm[x][i],fm[y][i])),x=f[x][i],y=f[y][i];
      return max(t,max(fm[x][0],fm[y][0]));
    }
    inline void read(int&a){char ch;while(!(((ch=getchar())>='0')&&(ch<='9')));a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))(a*=10)+=ch-'0';}
    int main(){
      read(H),read(W),read(n),read(Q);
      for(i=1;i<=H;i++)for(scanf("%s",s+1),j=1;j<=W;j++)a[i][j]=s[j]=='.';
      for(i=1;i<=n;i++)read(x),read(y),bfs(x,y,0,i),fa[i]=i;
      while(h<=t){
        x=q[h][0],y=q[h++][1],z=dis[x][y][0]+1,p=dis[x][y][1];
        bfs(x-1,y,z,p),bfs(x+1,y,z,p),bfs(x,y-1,z,p),bfs(x,y+1,z,p);
      }
      for(i=1;i<=H;i++)for(j=1;j<W;j++)check(i,j,i,j+1);
      for(i=1;i<H;i++)for(j=1;j<=W;j++)check(i,j,i+1,j);
      for(i=0;i<=mx;i++)for(E*p=e[i];p;p=p->nxt)if(F(p->x)!=F(p->y))add(p->x,p->y,i),add(p->y,p->x,i),fa[fa[p->x]]=fa[p->y];
      for(i=1;i<=n;i++)if(!d[i])dfs(i,0,0);
      while(Q--)read(x),read(y),printf("%d
    ",ask(x,y));
      return 0;
    }
    

      

  • 相关阅读:
    用vuex写了一个购物车H5页面的示例代码
    css如何引入外部字体?
    移动开发中更好的图片自适应
    常见样式问题七、word-break、word-wrap、white-space区别
    你真的了解word-wrap和word-break的区别吗?
    css中word-break、word-wrap和white-space的区别
    另辟蹊径:vue单页面,多路由,前进刷新,后退不刷新
    应该用forEach改变数组的值吗? 原生JS forEach()和map()遍历的异同点
    Vue 全家桶介绍
    Spring MVC配置MyBatis输出SQL
  • 原文地址:https://www.cnblogs.com/clrs97/p/4741153.html
Copyright © 2020-2023  润新知