2012年佛山市GDOI选拔赛题 加边

    xiaoxiao2021-03-25  12

    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; }
    转载请注明原文地址: https://ju.6miu.com/read-114619.html

    最新回复(0)