제출 #5705

#제출 시각아이디문제언어결과실행 시간메모리
5705cki86201물병 (JOI14_bottle)C++98
100 / 100
1576 ms144372 KiB
#include<stdio.h>
#include<algorithm>
using namespace std;

#define X first
#define Y second
typedef pair<int,int> Pi;

int H, W, P, Q;
char ch[2020][2020];
Pi inp[200020];
int Que[2002*2002];
int wh[2002*2002], di[2002*2002];
Pi vec[2002*2002];
int topv;
bool chk[2002*2002];
int xx[4] = {0, 1, 0, -1}, yy[4] = {1, 0, -1, 0};
int st[200020], en[400040], nxt[400040], len[400040];
inline void addE(int s,int e,int c,int l){nxt[c]=st[s],st[s]=c,en[c]=e,len[c]=l;}
inline void add(int s,int e,int &c,int l){addE(s,e,++c,l);addE(e,s,++c,l);}
struct edge{
	edge(){}
	edge(int s,int e,int l):s(s),e(e),l(l){}
	int s, e, l;
	bool operator<(const edge &a)const{
		return l<a.l;
	}
}E[1000010];
int top;

struct unf{
	static const int N_ = 200020;
	unf(){for(int i=0;i<N_;i++)p[i] = i, w[i] = 1;}
	int p[N_], w[N_];
	int Find(int x){
		if(p[x] == x)return x;
		return p[x] = Find(p[x]);
	}
	bool Union(int x,int y){
		x = Find(x), y = Find(y);
		if(x == y)return false;
		if(w[x] > w[y])w[x] += w[y], p[y] = x;
		else w[y] += w[x], p[x] = y;
		return true;
	}
	bool chk(int x,int y){return Find(x) == Find(y);}
}uf;

int up[200020][18];
int mx[200020][18];
int dep[200020];
bool vis[200020];

void dfs(int x)
{
	vis[x] = 1;
	for(int i=st[x];i;i=nxt[i])
		if(!vis[en[i]]){
			dep[en[i]] = dep[x] + 1;
			up[en[i]][0] = x;
			mx[en[i]][0] = len[i];
			for(int j=1;j<18;j++){
				up[en[i]][j] = up[ up[en[i]][j-1] ][j-1];
				mx[en[i]][j] = max(mx[en[i]][j-1], mx[up[en[i]][j-1]][j-1]);
			}
			dfs(en[i]);
		}
}

int Get(int x,int y)
{
	if(dep[x] < dep[y])swap(x,y);
	int res = 0;
	for(int i=0;i<18;i++){
		if(1<<i&(dep[x]-dep[y]))res = max(res, mx[x][i]), x = up[x][i];
	}
	if(x == y)return res;
	for(int i=17;i>=0;i--)
		if(up[x][i] != up[y][i]){
			res = max(res, mx[x][i]);
			res = max(res, mx[y][i]);
			x = up[x][i], y = up[y][i];
		}
	return max(res, max(mx[y][0], mx[x][0]));
}

int main()
{
	scanf("%d%d%d%d",&H,&W,&P,&Q);
	int i;
	for(i=0;i<H;i++)scanf("%s",ch[i]);
	int *fr = Que, *re = Que;
	for(i=1;i<=P;i++){
		scanf("%d%d",&inp[i].X,&inp[i].Y);
		--inp[i].X; --inp[i].Y;
		int a = inp[i].X * W + inp[i].Y;
		*fr++ = a; wh[a] = i; chk[a] = 1;
	}
	int now = 0;
	while(fr != re){
		int t = *re++;
		if(di[t] != now){
			now = di[t];
			while(topv--)uf.Union(vec[topv].X, vec[topv].Y);
			topv = 0;
		}
		for(i=0;i<4;i++){
			int tx = t/W + xx[i];
			int ty = t%W + yy[i];
			if(tx < 0 || tx >= H || ty < 0 || ty >= W || ch[tx][ty] == '#')continue;
			int nex = tx*W+ty;
			if(!chk[nex]){
				*fr++ = nex;
				di[nex] = di[t] + 1;
				wh[nex] = wh[t];
				chk[nex] = 1;
			}
			if(chk[nex] && uf.chk(wh[nex], wh[t]))continue;
			if(chk[nex])E[top++] = edge(wh[nex], wh[t], di[t] + di[nex]), vec[topv++] = Pi(wh[nex], wh[t]);
		}
	}
	sort(E, E+top);
	uf = unf();
	int c_edge = 2;
	for(i=0;i<top;i++)if(uf.Union(E[i].s, E[i].e))add(E[i].s, E[i].e, c_edge, E[i].l);
	for(i=1;i<=P;i++)if(!vis[i])dfs(i);
	for(int tt=1;tt<=Q;tt++){
		int x, y;
		scanf("%d%d",&x,&y);
		if(!uf.chk(x,y))printf("-1\n");
		else printf("%d\n",Get(x,y));
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...