POJ 2375 Cow Ski Area 强连通图最少添边数
2014-04-19 16:39
323 查看
题目来源:POJ 2375 Cow Ski Area
题意:n*m的一个矩阵 如果在一个点上 可以往上下左右4个点 并且必须大于等于要去的点 可以安装一个任意门 每个任意门可以连接容易2个点
求最少安装多少个任意门 可以是全通连通
思路:强连通分量缩点 求出度为0和入读为0的连通分量2者的最大值 特判全图强连通的情况
题意: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; }
相关文章推荐
- 设计模式之迭代器模式
- ACM Same binary weight
- SP2010开发和VS2010专家"食谱"--第一章节--列表和事件接收器(7)--部署事件接收器
- 论存储IOPS和Throughput吞吐量之间的关系
- sqlserver2005 自动备份的维护计划图解教程
- 为什么兴趣图谱将重塑我们的社交网络及未来的商业
- Android Intent 的几种启动活动的方式
- Debian7.3 x86_64位系统无法启动adb如何解决
- opencv_协方差矩阵与协方差讲解
- region split流程分析
- Python第一步
- Java知识总结——对象创建过程
- 常用linux小工具介绍
- opencv_协方差矩阵与协方差讲解
- android之自定义ViewGroup和自动换行的布局的实现
- 02_Linux学习_命令
- 我们是这样使用腾讯风铃的!
- 目标跟踪学习笔记_4(particle filter初探3)
- Intent.setClass(this,className),第一个参数
- Redis配置文件参数说明