Description
给出一个大小为N × M (1 ≤ N, M ≤ 300)的矩形,矩形的每个位置有一个高度 h (1 ≤ h ≤ 1,000,000)。在相邻的格点间,你可以上下或者左右移动。但是你只能从高的格点走向不比它高的格点。相同高度的格点间两个方向都能移动。
现在,你需要计算出至少需要添加多少条双向边才能使到矩阵任意两点之间都可以互相到达
Solution
一眼题。枚举连边然后强联通分量一下找入度为0与出度为0中比较大的那个就行了
考试的时候脑抽了硬是没写出来
我还是太弱了
Code
#include <stdio.h>
#include <stack>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define min(x, y) (x)<(y)?(x):(y)
#define max(x, y) (x)>(y)?(x):(y)
#define N 200001
#define E N * 21 + 1
#define L 501
struct edge{int x, y, next;}e[E];
int ls[N];
inline void addEdge(int &cnt, int x, int y){
cnt += 1; e[cnt] = (edge){x, y, ls[x]}; ls[x] = cnt;
}
using std:: stack;
stack<int> st;
int inStack[N], comp[N], dfn[N], low[N], cnt;
inline int dfs(int now){
dfn[now] = low[now] = ++ cnt;
inStack[now] = 1;
st.push(now);
erg(i, now){
if (!dfn[e[i].y]){
dfs(e[i].y);
low[now] = min(low[now], low[e[i].y]);
}else if (dfn[e[i].y] && inStack[e[i].y]){
low[now] = min(low[now], dfn[e[i].y]);
}
}
if (dfn[now] == low[now]){
comp[0] ++;
for (int tmp = 0; tmp ^ now; ){
tmp = st.top(); st.pop();
comp[tmp] = comp[0];
inStack[tmp] = 0;
}
}
}
inline void tarjan(int n){
cnt = 0;
rep(i, 1, n){
if (!dfn[i]){
dfs(i);
}
}
}
int rc[L][L], idx[L][L], ind[N], oud[N];
int main(void){
int n, m;
scanf("%d%d", &n, &m);
rep(i, 1, n){
rep(j, 1, m){
scanf("%d", &rc[i][j]);
idx[i][j] = ++ idx[0][0];
}
}
int edgeCnt = 0;
rep(i, 1, n){
rep(j, 1, m){
if (i > 1 && rc[i][j] >= rc[i - 1][j]){
addEdge(edgeCnt, idx[i][j], idx[i - 1][j]);
}
if (j > 1 && rc[i][j] >= rc[i][j - 1]){
addEdge(edgeCnt, idx[i][j], idx[i][j - 1]);
}
if (i < n && rc[i][j] >= rc[i + 1][j]){
addEdge(edgeCnt, idx[i][j], idx[i + 1][j]);
}
if (j < m && rc[i][j] >= rc[i][j + 1]){
addEdge(edgeCnt, idx[i][j], idx[i][j + 1]);
}
}
}
tarjan(n * m);
rep(i, 1, edgeCnt){
if (comp[e[i].x] ^ comp[e[i].y]){
ind[comp[e[i].y]] ++;
oud[comp[e[i].x]] ++;
}
}
int indCnt = 0, oudCnt = 0;
rep(i, 1, comp[0]){
if (!ind[i]){
indCnt ++;
}
if (!oud[i]){
oudCnt ++;
}
}
int ans = max(indCnt, oudCnt);
if (comp[0] == 1){
ans = 0;
}
printf("%d\n", ans);
return 0;
}