zoukankan      html  css  js  c++  java
  • bzoj 4242 水壶 (多源最短路+最小生成树+启发式合并)

    4242: 水壶

    Time Limit: 50 Sec  Memory Limit: 512 MB
    Submit: 1028  Solved: 261
    [Submit][Status][Discuss]

    Description

    JOI君所居住的IOI市以一年四季都十分炎热著称。
    IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物、原野、墙壁之一。建筑物的区域有P个,编号为1...P。
    JOI君只能进入建筑物与原野,而且每次只能走到相邻的区域中,且不能移动到市外。
    JOI君因为各种各样的事情,必须在各个建筑物之间往返。虽然建筑物中的冷气设备非常好,但原野上的日光十分强烈,因此在原野上每走过一个区域都需要1单位的水。此外,原野上没有诸如自动售货机、饮水处之类的东西,因此IOI市的市民一般都携带水壶出行。大小为x的水壶最多可以装x单位的水,建筑物里有自来水可以将水壶装满。
    由于携带大水壶是一件很困难的事情,因此JOI君决定携带尽量小的水壶移动。因此,为了随时能在建筑物之间移动,请你帮他写一个程序来计算最少需要多大的水壶。
    现在给出IOI市的地图和Q个询问,第i个询问(1<=i<=Q)为“在建筑物Si和Ti之间移动,最小需要多大的水壶?”,请你对于每个询问输出对应的答案。

    Input

    第一行四个空格分隔的整数H,W,P,Q,表示IOI市被分成了纵H*横W块区域,有P个建筑物,Q次询问。
    接下来H行,第i行(1<=i<=H)有一个长度为W的字符串,每个字符都是’.’或’#’之一,’.’表示这个位置是建筑物或原野,’#’表示这个位置是墙壁。
    接下来P行描述IOI市每个建筑物的位置,第i行(1<=i<=P)有两个空格分隔的整数Ai和Bi,表示第i个建筑物的位置在第Ai行第Bi列。保证这个位置在地图中是’.’
    接下来Q行,第i行(1<=i<=Q)有两个空格分隔的整数Si和Ti,表示第i个询问为“在建筑物Si和Ti之间移动,最小需要多大的水壶?”

    Output

    输出Q行,第i行(1<=i<=Q)一个整数,表示在建筑物Si和Ti之间移动最小需要多大的水壶。
    如果无法到达,输出-1。此外,如果不需要经过原野就能到达,输出0。

    Sample Input

    5 5 4 4
    .....
    ..##.
    .#...
    ..#..
    .....
    1 1
    4 2
    3 3
    2 5
    1 2
    2 4
    1 3
    3 4

    Sample Output

    3
    4
    4
    2

    HINT

    1<=H<=2000

    1<=W<=2000

    2<=P<=2*10^5

    1<=Q<=2*10^5

    1<=Ai<=H(1<=i<=P)

    1<=Bi<=W(1<=i<=P)

    (Ai,Bi)≠(Aj,Bj)(1<=i<j<=P)

    1<=Si<Ti<=P(1<=i<=Q)

    跟bzoj4144题一样。。不过由于每条边距离相等,所以我们要把优先队列换成普通队列来减少时间。我实在是口算不出来这个时间是多少,然后一开始优先队列一直过不了。看了人家ac代码是普通队列一改就过了。。。orz。不过时间也是挺极限的46s。反正过啦!

      1 #include<bits/stdc++.h>
      2 #define clr(x) memset(x,0,sizeof(x))
      3 #define clr_1(x) memset(x,-1,sizeof(x))
      4 #define INF 0x3f3f3f3f
      5 #define LL long long
      6 #define pb push_back
      7 #define mod 1000000007
      8 #define ls(i) (i<<1)
      9 #define rs(i) (i<<1|1)
     10 #define mp make_pair
     11 #define fi first
     12 #define se second
     13 using namespace std;
     14 const int N=2e3+10;
     15 const int M=2e5+10;
     16 typedef pair<int,int> pii;
     17 typedef pair<LL,pii> plii;
     18 queue<pii> que;
     19 int mart[N][N];
     20 char s[N];
     21 LL dis[N][N];
     22 int pre[N][N];
     23 bool vis[N][N];
     24 struct edge
     25 {
     26     int u,v;
     27     LL w;
     28     edge(int _u,int _v,LL _w):u(_u),v(_v),w(_w) {}
     29 };
     30 vector<edge> e;
     31 int dirx[4]={0,0,1,-1},diry[4]={1,-1,0,0};
     32 void dij(int n,int m)
     33 {
     34     while(!que.empty())
     35     {
     36         pii p=que.front();
     37         que.pop();
     38         int x=p.fi;
     39         int y=p.se;
     40         LL d=dis[x][y];
     41         if(vis[x][y]) continue;
     42         vis[x][y]=1;
     43         for(int i=0;i<4;i++)
     44         {
     45             int a=x+dirx[i];
     46             int b=y+diry[i];
     47             if(mart[a][b]) continue;
     48             if(!pre[a][b] || dis[a][b]>d+1)
     49             {
     50                 dis[a][b]=d+1;
     51                 pre[a][b]=pre[x][y];
     52                 que.push(mp(a,b));
     53             }
     54             else if(pre[a][b]!=pre[x][y])
     55                 e.pb(edge(pre[a][b],pre[x][y],dis[x][y]+dis[a][b]));
     56         }
     57     }
     58 }
     59 int fa[M],rfa[M];
     60 int rk[M],dep[M];
     61 LL up[M];
     62 bool cmp(edge a,edge b) {return a.w<b.w;}
     63 int Find(int u) { return fa[u]==u?u:fa[u]=Find(fa[u]);}
     64 void Union(int n)
     65 {
     66     sort(e.begin(),e.end(),cmp);
     67     for(int i=1;i<=n;i++)
     68         fa[i]=i,rk[i]=1;
     69     int sz=e.size();
     70     for(int i=0;i<sz;i++)
     71     {
     72         int x=e[i].u;
     73         int y=e[i].v;
     74         LL w=e[i].w;
     75         x=Find(x),y=Find(y);
     76         if(x==y) continue;
     77         if(rk[x]<rk[y]) swap(x,y);
     78         if(rk[x]==rk[y]) rk[x]++;
     79         fa[y]=x,rfa[y]=x,up[y]=w;
     80     }
     81     return ;
     82 }
     83 void dealdep(int u)
     84 {
     85     if(Find(u)==u)
     86     {
     87         dep[u]=1;
     88         return ;
     89     }
     90     dealdep(rfa[u]);
     91     dep[u]=dep[rfa[u]]+1;
     92     return ;
     93 }
     94 LL solve(int u,int v)
     95 {
     96     LL maxn=0;
     97     if(Find(u)!=Find(v)) return -1;
     98     if(dep[u]<dep[v]) swap(u,v);
     99     while(dep[u]>dep[v])
    100     {
    101         maxn=max(maxn,up[u]);
    102         u=rfa[u];
    103     }
    104     while(u!=v)
    105     {
    106         maxn=max(maxn,up[u]);
    107         maxn=max(maxn,up[v]);
    108         u=rfa[u],v=rfa[v];
    109     }
    110     return maxn;
    111 }
    112 int main()
    113 {
    114     int n,m,k,q;
    115     scanf("%d%d%d%d",&n,&m,&k,&q);
    116     for(int i=1;i<=n;i++)
    117     {
    118         scanf("%s",s+1);
    119         for(int j=1;j<=m;j++)
    120             if(s[j]=='.') mart[i][j]=0;
    121             else mart[i][j]=1;
    122     }
    123     for(int i=1;i<=m+1;i++)
    124         mart[0][i]=mart[n+1][i]=1;
    125     for(int i=1;i<=n+1;i++)
    126         mart[i][0]=mart[i][m+1]=1;
    127     clr_1(dis);
    128     for(int i=1;i<=k;i++)
    129     {
    130         int u,v;
    131         scanf("%d%d",&u,&v);
    132         dis[u][v]=0;
    133         pre[u][v]=i;
    134         que.push(mp(u,v));
    135     }
    136     dij(n,m);
    137     Union(k);
    138     for(int i=1;i<=k;i++)
    139         if(!dep[i]) dealdep(i);
    140 //    for(int i=1;i<=k;i++)
    141 //        cout<<"pos:"<<pt[i]/m+1<<" "<<pt[i]%m+1<<" blk:"<<Find(pt[i])/m+1<<" "<<Find(pt[i])%m+1<<" fa:"<<rfa[pt[i]]/m+1<<" "<<rfa[pt[i]]%m+1<<" dep:"<<dep[pt[i]]<<" val:"<<up[pt[i]]<<endl;
    142     while(q--)
    143     {
    144         int u,v;
    145         scanf("%d%d",&u,&v);
    146         printf("%lld
    ",solve(u,v));
    147     }
    148     return 0;
    149 }
    View Code
  • 相关阅读:
    java后端工具积累
    Java基础面试题整理
    MySql常问面试题
    jvm及并发面试题
    中间件redis kafka面试题
    笔记
    解决Git操作报错
    view的state和drawable的state 源码分析
    flutter_6_动态化简介
    有关namespace 命名空间
  • 原文地址:https://www.cnblogs.com/wujiechao/p/9185047.html
Copyright © 2011-2022 走看看