zoukankan      html  css  js  c++  java
  • [JOISC2014]水筒

    OJ题号:
      BZOJ4242、AtCoder-JOISC2014E

    题目大意:
      给你一个h*w的网格图,每个格子可能是空地、障碍物和建筑物。
      你只可以从空地上走过或者从建筑物中穿过。
      建筑物总共有p个,现在有q组询问,求从建筑物A到建筑物B的过程中在空地上连续走过的最长一段路最短能是多少。
    思路:
      为了保证走过的最长路最短,我们可以对所有的建筑物及其路径构造最小生成树。
      正确性显然:为了保证最长路最短,我们要使所有能走的边尽量小,这实际上就是一个贪心,也就是我们所熟知的Kruskal算法。
      题目并没有告诉你总共有哪些边,而原图又是一个网格图,暴力算出所有的边显然会TLE,因此需要考虑如何将所有可能边算出来。
      我们可以对原图进行BFS,首先将所有的建筑物加入到队列中,然后对每个建筑物向外扩展。
      如果当两个建筑物所扩展到的范围出现重叠时,我们就将经由该格点的连接两个建筑物的路径加入边集。
      如果两个建筑物最后扩展到的范围被其它建筑物的范围所阻断,不能直接相连,那么说明这两个点可以经由另一个点中转达到更优。
      然而两个建筑物可能会重叠好几次,这时候并不一定要判重,因为每个格点上最多会被连4条边,整个图就最多有h*w*4条边,事实上远远达不到这个值。
      实践证明用map判重反而比不判重要慢。
      每次还要特判重叠的范围是不是属于同一个建筑物,不然会多加很多边,还会MLE。
      然后跑一遍Kruskal求最小生成树即可。
      最后的询问就相当于树上RMQ,用稀疏表或者树剖之类的数据结构维护一下即可。
      然后交到AtCoder上随随便便拿了Rank1,吊打yutaka1999。
      交到BZOJ上无限RE。
      不放心,觉得是系统环境的问题,用Ubuntu测了一发,还是AC。
      找管理员要数据被告知就是官方数据。
      把C++流读入改成C标准读入就A了。

      1 #include<queue>
      2 #include<vector>
      3 #include<cstdio>
      4 #include<cctype>
      5 #include<algorithm>
      6 
      7 inline int getint() {
      8     register char ch;
      9     while(!isdigit(ch=getchar()));
     10     register int x=ch^'0';
     11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     12     return x;
     13 }
     14 inline bool isMasu(const char &ch) {
     15     return ch=='.'||ch=='#';
     16 }
     17 inline char getmasu() {
     18     register char ch;
     19     while(!isMasu(ch=getchar()));
     20     return ch;
     21 }
     22 
     23 const int inf=0x7fffffff;
     24 const int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
     25 const int H=2001,W=2001,P=200001,logP=18,Q=200001;
     26 
     27 int h,w,p;
     28 int map[H][W]={{0}};
     29 
     30 class DisjointSet {
     31     private:
     32         int anc[P];
     33         int find(const int &x) {
     34             return x==anc[x]?x:anc[x]=find(anc[x]);
     35         }
     36     public:
     37         DisjointSet() {
     38             for(register int i=0;i<P;i++) {
     39                 anc[i]=i;
     40             }
     41         }
     42         void Union(const int &x,const int &y) {
     43             anc[find(x)]=find(y);
     44         }
     45         bool isConnected(const int &x,const int &y) {
     46             return find(x)==find(y);
     47         }
     48 };
     49 DisjointSet s;
     50 
     51 struct Edge1 {
     52     int u,v,w;
     53     bool operator < (const Edge1 &another) const {
     54         return w<another.w;
     55     }
     56 };
     57 std::vector<Edge1> e1;
     58 
     59 struct Edge {
     60     int to,w;
     61 };
     62 std::vector<Edge> e[P];
     63 inline void add_edge(const int &u,const int &v,const int &w) {
     64     e[u].push_back((Edge){v,w});
     65 }
     66 
     67 struct State {
     68     int dis,root;
     69 };
     70 State vis[H][W];
     71 
     72 struct Point {
     73     int x,y;
     74     bool onMap() const {
     75         return x&&y&&x<=h&&y<=w;
     76     }
     77 };
     78 std::queue<Point> q;
     79 
     80 inline void bfs() {
     81     for(register int i=1;i<=h;i++) {
     82         for(register int j=1;j<=w;j++) {
     83             if(map[i][j]>0) {
     84                 q.push((Point){i,j});
     85                 vis[i][j]=(State){0,map[i][j]};
     86             } else {
     87                 vis[i][j]=(State){-1,0};
     88             }
     89         }
     90     }
     91     while(!q.empty()) {
     92         const Point a=q.front();
     93         q.pop();
     94         for(register int i=0;i<4;i++) {
     95             Point b=(Point){a.x+dx[i],a.y+dy[i]};
     96             if(!b.onMap()) continue;
     97             if(!~map[b.x][b.y]) continue;
     98             if(vis[b.x][b.y].root) {
     99                 const int &u=vis[a.x][a.y].root,&v=vis[b.x][b.y].root,w=vis[a.x][a.y].dis+vis[b.x][b.y].dis;
    100                 if(u==v) continue;
    101                 e1.push_back((Edge1){u,v,w});
    102             } else {
    103                 vis[b.x][b.y]=(State){vis[a.x][a.y].dis+1,vis[a.x][a.y].root};
    104                 q.push((Point){b.x,b.y});
    105             }
    106         }
    107     }
    108 }
    109 
    110 inline void kruskal() {
    111     std::sort(e1.begin(),e1.end());
    112     for(register std::vector<Edge1>::iterator i=e1.begin();i!=e1.end();i++) {
    113         const int &u=i->u,&v=i->v,&w=i->w;
    114         if(s.isConnected(u,v)) continue;
    115         s.Union(u,v);
    116         add_edge(u,v,w);
    117         add_edge(v,u,w);
    118     }
    119     e1.clear();
    120 }
    121 
    122 class SparseTable {
    123     private:
    124         int dep[P];
    125         int anc[P][logP],max[P][logP];
    126         int log2(const float &x) const {
    127             return ((unsigned&)x>>23&255)-127;
    128         }
    129         void dfs(const int &x) {
    130             dep[x]=dep[anc[x][0]]+1;
    131             for(int i=1;i<=log2(dep[x]);i++) {
    132                 anc[x][i]=anc[anc[x][i-1]][i-1];
    133                 max[x][i]=std::max(max[x][i-1],max[anc[x][i-1]][i-1]);
    134             }
    135             for(std::vector<Edge>::iterator i=e[x].begin();i!=e[x].end();i++) {
    136                 const int &y=i->to;
    137                 if(y==anc[x][0]) continue;
    138                 anc[y][0]=x;
    139                 max[y][0]=i->w;
    140                 dfs(y);
    141             }
    142             e[x].clear();
    143         }
    144     public:
    145         void init() {
    146             for(register int i=1;i<=p;i++) {
    147                 if(!dep[i]) {
    148                     dfs(i);
    149                 }
    150             }
    151         }
    152         int query(int x,int y) const {
    153             if(!s.isConnected(x,y)) return -1;
    154             int ret=0;
    155             while(dep[x]!=dep[y]) {
    156                 if(dep[x]<dep[y]) {
    157                     std::swap(x,y);
    158                 }
    159                 for(register int i=log2(dep[x]);i>=0;i--) {
    160                     if(dep[anc[x][i]]>=dep[y]) {
    161                         ret=std::max(ret,max[x][i]);
    162                         x=anc[x][i];
    163                     }
    164                 }
    165             }
    166             if(x==y) return ret;
    167             for(register int i=log2(dep[x]);i>=0;i--) {
    168                 if(anc[x][i]!=anc[y][i]) {
    169                     ret=std::max(ret,std::max(max[x][i],max[y][i]));
    170                     x=anc[x][i],y=anc[y][i];
    171                 }
    172             }
    173             ret=std::max(ret,std::max(max[x][0],max[y][0]));
    174             return ret;
    175         }
    176 };
    177 SparseTable t;
    178 
    179 int main() {
    180     h=getint(),w=getint(),p=getint();
    181     const int q=getint();
    182     for(register int i=1;i<=h;i++) {
    183         for(register int j=1;j<=w;j++) {
    184             if(getmasu()=='#') map[i][j]=-1;
    185         }
    186     }
    187     for(register int i=1;i<=p;i++) {
    188         const int x=getint(),y=getint();
    189         map[x][y]=i;
    190     }
    191     bfs();
    192     kruskal();
    193     t.init();
    194     for(register int i=0;i<q;i++) {
    195         printf("%d
    ",t.query(getint(),getint()));
    196     }
    197     return 0;
    198 }

     附官方题解:

  • 相关阅读:
    50个jQuery 插件可将你的网站带到另外一个高度
    Web 开发中 20 个很有用的 CSS 库
    【算法】1、约瑟夫环
    智造微博
    银河系中央超大黑洞可能是个虫洞 其连接着两个不同的时空。
    创意文案:我害怕阅读的人
    解决Oracle ORA-00984: column not allowed here
    舌尖上的程序员
    技术贴 本地代码与svn关联教程 svn upgrade问题解决
    Aimp3的播放列表 按评分排序 落雨
  • 原文地址:https://www.cnblogs.com/skylee03/p/7574282.html
Copyright © 2011-2022 走看看