POJ 2375 Cow Ski Area 强连通图最少添边数

来源:互联网 发布:elliott smith 知乎 编辑:程序博客网 时间:2024/05/12 09:29

题目来源:POJ 2375 Cow Ski Area

题意:n*m的一个矩阵 如果在一个点上 可以往上下左右4个点 并且必须大于等于要去的点 可以安装一个任意门 每个任意门可以连接容易2个点

求最少安装多少个任意门 可以是全通连通

思路:强连通分量缩点 求出度为0和入读为0的连通分量2者的最大值 特判全图强连通的情况

#include <cstdio>#include <cstring>#include <vector>#include <stack>#include <algorithm>using namespace std;const int maxn = 510;int first[maxn*maxn];int next[maxn*maxn];stack <int> s;int pre[maxn*maxn];int low[maxn*maxn];int sccno[maxn*maxn];//每个点所在强联通分量的scc_cnt int in[maxn*maxn];//每个强联通分量的入度 int out[maxn*maxn];int dfs_clock;int scc_cnt;int n, m, nm;int a[maxn][maxn];int cnt;int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};struct edge{    int v, next;}e[maxn*maxn*4];void ad(int x, int y){    e[cnt].next = first[x];    e[cnt].v = y;    first[x] = cnt++;}void dfs(int u){pre[u] = low[u] = ++dfs_clock;s.push(u);for(int ee = first[u]; ee != -1; ee = e[ee].next){int v = e[ee].v;if(!pre[v]){dfs(v);low[u] = min(low[u], low[v]);}else if(!sccno[v]){low[u] = min(low[u], pre[v]);}}if(low[u] == pre[u]){scc_cnt++;while(1){int x = s.top();s.pop();sccno[x] = scc_cnt;if(x == u)break;}}}void find_scc(){dfs_clock = scc_cnt = 0;memset(sccno, 0, sizeof(sccno));memset(pre, 0, sizeof(pre));for(int i = 0; i < nm; i++)if(!pre[i])dfs(i);}void ok(int x, int y){for(int i = 0; i < 4; i++){int xx = x + dir[i][0];int yy = y + dir[i][1];if(xx < 0 || xx >= n || yy < 0 || yy >= m)continue;if(a[x][y] >= a[xx][yy]){ad(x*m+y, xx*m+yy);}}}int main(){scanf("%d %d", &m, &n);nm = n*m;memset(first, -1, sizeof(first));memset(next, -1, sizeof(next));for(int i = 0; i < n; i++)for(int j = 0; j < m; j++)scanf("%d", &a[i][j]);cnt = 1;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){ok(i, j);}}find_scc();memset(in, 0, sizeof(in));memset(out, 0, sizeof(out));for(int u = 0; u < nm; u++){for(int ee = first[u]; ee != -1; ee = e[ee].next){int v = e[ee].v;if(sccno[u] != sccno[v]){in[sccno[v]]++;out[sccno[u]]++;}}}int sum1 = 0, sum2 = 0;for(int i = 1; i <= scc_cnt; i++){if(!in[i])sum1++;if(!out[i])sum2++;}int ans = max(sum1, sum2);if(scc_cnt == 1)ans = 0;printf("%d\n", ans);return 0;}


 

0 0
原创粉丝点击