India and China Origins
Accepts: 97
Submissions: 351
Time Limit: 2000/2000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
很久以前,中国和印度之间并没有喜马拉雅山相隔,两国的文化交流很频繁。随着喜马拉雅山海拔逐渐增加,两个地区的交流也越来越少,最终没有了来往。
假设当时的地形和我画的一样,蓝色部分代表海洋,而且当时人们还没有发明轮船。黄色部分代表沙漠,而且沙漠上经常有野鬼散步,所以人们不敢到沙漠中行走。黑色的格子表示山峰,这些山峰都无比高大,所以人无法穿过。白色格子代表平原,人可以在平原上自由行走。人每次可以向相邻的四个格子走动。
此外,我们的考古学家发现还有一些山峰会逐渐形成,通过研究发现,位置在 (x, y)(x,y) (保证该位置之前没有山峰)的地方在 ii 年后出现了山峰。现在给你若干个位置出现山峰的时间,你可以计算出中国和印度之间的联系最早被彻底切断的时间吗?
输入描述
多组测试数据, 第一行为组数T(T\leq 10)T(T≤10)。每组测试数据第一行包含两个数 N, M (1 \leq N, M \leq 500)N,M(1≤N,M≤500), 表示地图的大小。接下来 NN 行长度为 MM 的 0101 字符串。00代表白色格子,11 代表山峰。接下来有 Q(1\leq Q \leq N\times M)Q(1≤Q≤N×M) 行,第 i(1\leq i \leq Q)i(1≤i≤Q) 两个整数 (x,y),0 \leq x < N, 0 \leq y < M(x,y),0≤x<N,0≤y<M 表示在第 ii 年 (x,y)(x,y) 出现了一座山峰。
输出描述
对于每组测试数据,输出一个数, 表示两国最早失联的时间。如果最终两国之间还有联系则输出 -1。
输入样例
1
4 6
011010
000010
100001
001000
7
0 3
1 5
1 3
0 0
1 2
2 4
2 1
输出样例
4
Hint
从上图可以看到,两国在第四年彻底失去了联系。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 505, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int casenum, casei;
int n, m, g; int lft, rgt;
char s[N][N];
int f[N*N];
int yy[N*N], xx[N*N];
const int dy[8] = { -1,-1,-1,0,0,1,1,1 };
const int dx[8] = { 0,-1,1,-1,1,-1,0,1 };
int find(int x,int dep=0)
{
if (dep > 1e5)
{
int pause = 1;
}
return f[x] == x ? x : f[x] = find(f[x], dep + 1);
}
void merge(int o1, int y, int x)
{
if (y < 0 || y == n || x < 0 || x == m)return;
if (s[y][x] != '1')return;
int o2 = y*m + x;
o1 = find(o1);
o2 = find(o2);
//if (o1 != o2)f[o2] = o1; //这么写就会被制造出来的数据卡爆栈
if (o1 != o2)f[o1] = o2;
}
void MERGE(int i, int j)
{
int o = i*m + j;
for (int k = 0; k < 8; ++k)merge(o, i + dy[k], j + dx[k]);
if (j == 0)
{
o = find(o);
lft = find(lft);
if (o != lft)f[o] = lft;
}
if (j == m - 1)
{
o = find(o);
rgt = find(rgt);
if (o != rgt)f[o] = rgt;
}
}
vector< pair<int, int> >b;
void datamaker()
{
freopen("c://test//input.in", "w", stdout);
puts("1");
int n = 500, m = 500;
printf("%d %d\n", n, m);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)s[i][j] = '0';
puts(s[i]);
}
b.clear();
for (int i = 0; i < n; ++i)
{
if (i % 4 == 0)
{
for (int j = 1; j <= m - 2; ++j)b.push_back(MP(i, j));
}
else if (i % 4 == 1)
{
b.push_back(MP(i, m - 2));
}
else if (i % 4 == 2)
{
for (int j = m - 2; j >= 1; --j)b.push_back(MP(i, j));
}
else
{
b.push_back(MP(i, 1));
}
}
b.push_back(MP(n - 1, 0));
b.push_back(MP(0, m - 1));
int num = b.size();
printf("%d\n", num);
for (int i = 0; i < num; ++i)printf("%d %d\n", b[i].first, b[i].second);
}
int main()
{
//datamaker(); return 0;
fre();
scanf("%d", &casenum);
for (casei = 1; casei <= casenum; ++casei)
{
scanf("%d%d", &n, &m);
lft = n*m;
rgt = n*m + 1;
for (int i = 0; i <= rgt; ++i)f[i] = i;
for (int i = 0; i < n; ++i)scanf("%s", s[i]);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (s[i][j] == '1')MERGE(i, j);
}
}
scanf("%d", &g);
for (int i = 1; i <= g; ++i)scanf("%d%d", &yy[i], &xx[i]);
if (find(lft) == find(rgt))
{
puts("0");
continue;
}
int ans = -1;
for (int tim= 1; tim <= g; ++tim)
{
int i = yy[tim];
int j = xx[tim];
s[i][j] = '1';
MERGE(i, j);
if (find(lft) == find(rgt))
{
ans = tim;
break;
}
}
printf("%d\n", ans);
}
return 0;
}
/*
【trick&&吐槽】
错误更可能是逻辑错误,检查自己的考虑是否完备!
错误更可能是逻辑错误,检查自己的考虑是否完备!
错误更可能是逻辑错误,检查自己的考虑是否完备!
1,需要做8个方向的并查集操作。
2,要尽可能写的过程化,函数化,规范化。
3,BC会爆栈,我们考虑一下并查集在什么情况下会爆栈:
如果我们合并是往新的点上合并,那么对于一个蛇行的图,就会GG
4,二分答案BFS其实可以卡得接近TLE
【题意】
给你一个n*m的棋盘
问你经过多久,棋盘无法从第0行出发到达第n+1行
【类型】
并查集or二分答案bfs
【分析】
只要到达棋盘左右相连的时刻即可
什么时候棋盘左右相连呢?
并查集即可。
*/