water 灌水问题(最小生成树 搜索)
来源:互联网 发布:驾驶员网络培训 编辑:程序博客网 时间:2024/06/14 21:58
10.3
water
思路:
一个块的高度就是从这走出矩形所有路径上最大值的最小。相邻块连边,边权为两块的较大值,矩形边界的块(人工加一圈为0的圈)向“矩形外”连(把“矩形外”抽象成一个S点),权值为 max(高度, 0) ,做最小生成树。
这样就能找到最优解,那么怎么统计答案呢?从S开始dfs记录到每个点的路径最大值。
时间复杂度 O(nmlognm)
贴一份 berrykanry的代码
#include<stdio.h>#include<algorithm>using namespace std;typedef long long dnt;struct edge{ int u,v,last; dnt w;}ad[2000010],ed[2000010];int n,m,fa[200010],head[2000010];dnt dep[2000010],a[2000010];int num=0,tot=0;bool cmp(const edge &a,const edge &b){ return a.w<b.w;}void ade(int u,int v,dnt w){ tot++; ad[tot].u=u,ad[tot].v=v,ad[tot].w=w;}void add(int u, int v, dnt w){ num++; ed[num].v=v; ed[num].w=w; ed[num].last=head[u]; head[u]=num;}int getfather(int x){ if(x==fa[x]) return x; return fa[x]=getfather(fa[x]);}void Kruscal(){ int cnt = 0; for(int i=0; i<=n*m; i++) fa[i]=i; sort(ad+1, ad+tot+1, cmp); for(int i=1; i<=tot; i++){ int x = getfather(ad[i].u), y = getfather(ad[i].v); if(x != y){ fa[x] = y, cnt++; add(ad[i].u, ad[i].v, ad[i].w); add(ad[i].v, ad[i].u, ad[i].w); } if(cnt == n*m) break ; }}void dfs(int u, int f){ for(int i=head[u]; i; i=ed[i].last){ int v = ed[i].v; if(v == f) continue ; dep[v] = max(dep[u], ed[i].w); dfs(v, u); }}int main(){ freopen("water.in", "r", stdin); freopen("water.out", "w", stdout); scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) scanf("%I64d", &a[(i-1)*n+j]); for(int i=1; i<=n; i++) for(int j=1; j<=m; j++){ int S=(i-1)*n+j; int A=(j==1) ? 0 : (i-1)*n+j-1; int B=(j==m) ? 0 : (i-1)*n+j+1; int C=(i==1) ? 0 : (i-2)*n+j; int D=(i==n) ? 0 : i*n+j; ade(S,A,max(a[S],a[A])),ade(S,B,max(a[S],a[B])); ade(S,C,max(a[S],a[C])),ade(S,D,max(a[S],a[D])); } Kruscal(); dfs(0, 0); for(int i=1; i<=n; i++, printf("\n")) for(int j=1;j<=m;j++){ int S=(i-1)*n+j; printf("%I64d ",max(dep[S]-a[S],1LL*0)); } return 0;}
’搜索‘做法
从外向内dfs,a为实际高度,h为积水后高度。
用堆维护起点(由大到小更新)
#include <iostream>#include <cstring>#include <cstdio>#include <queue>#define LL long long#define N 400using namespace std;struct place{ int x, y; LL v; bool operator < (const place &a) const{ return v > a.v; }};inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}priority_queue <place> q;int n,m;LL a[N][N], h[N][N];bool vis[N][N];int dx[4] = {1,-1,0,0};int dy[4] = {0,0,1,-1};int main(){ freopen ("water.in", "r", stdin); freopen ("water.out", "w", stdout); n = read(), m = read(); for(register int i=1; i<=n; ++i) for(register int j=1; j<=m; ++j) a[i][j] = read(), h[i][j] = a[i][j]; for(register int i=0; i<=n+1; ++i) for(register int j=0; j<=m+1; ++j) if(i==0 || i==n+1 || j==0 || j==m+1){ vis[i][j] = 1; q.push((place){i, j, h[i][j]}); } while( !q.empty() ){ place u = q.top(); q.pop(); for(int i=0; i<=3; ++i){ int x = u.x + dx[i], y = u.y + dy[i]; if(x>=0 && x<=n+1 && y>=0 && y<=m+1 && !vis[x][y]){ if(h[x][y] < h[u.x][u.y]) h[x][y] = h[u.x][u.y]; vis[x][y] = 1; q.push((place){x, y, h[x][y]}); } } } for(register int i=1; i<=n; ++i){ for(register int j=1; j<=m; ++j) printf("%d ", h[i][j] - a[i][j]); cout << endl; } return 0;}
阅读全文
0 0
- water 灌水问题(最小生成树 搜索)
- *【bzoj 1601】灌水(最小生成树)
- 【bzoj1601】灌水 最小生成树
- bzoj 1601: [Usaco2008 Oct]灌水 (最小生成树)
- bzoj 1601: [Usaco2008 Oct]灌水(最小生成树)
- [Usaco2008 Oct]灌水 最小生成树
- 【BZOJ1601】[Usaco2008 Oct]灌水【最小生成树】
- 【bzoj1601】【uscao2008 oct】【灌水】【最小生成树】
- [BZOJ]1601 灌水 最小生成树
- 【bzoj1601】【Usaco2008 Oct】灌水 (最小生成树) 题解&代码
- [bzoj1601]: [Usaco2008 Oct]灌水牧场行走 最小生成树
- bzoj 1601: [Usaco2008 Oct]灌水 最小生成树
- BZOJ 1601 [Usaco2008 Oct]灌水(最小生成树)
- 【BzoJ 1601】【灌水】【最小生成树】【贪心决策】【并查集】
- hdoj--4009--Transfer water(最小生成图)
- 最小生成树问题
- 最小生成树问题
- 最小生成树问题
- nth_element()
- console.log 打印object
- HDU 5521 Meeting(最短路)
- gcc的详细用法
- oracle锁与死锁概念,阻塞产生的原因以及解决方案
- water 灌水问题(最小生成树 搜索)
- 页面不缓存设置
- jenkins --部署项目到服务器需要的脚本
- MATLAB图像处理基础知识3 替换矩阵的数值A(A<0) = 1
- 51单片机外设之——矩阵键盘(传统法一)
- 感知机简介及python代码简介
- pandas入门学习
- 最长回文子串(马拉车)
- 使用splash爬去JavaScript动态请求的内容