题目大意:有一块地,分成nxm块。有的块上长着草,有的块上是荒地。将任何一块长着草的块上的草拔掉都需要花费d个力气,往任何一块荒地上种上草都需要花费f个力气,在草和荒地之间架一个篱笆需要花费b个力气,如果一块草地四周都是荒地,则得花掉4b个力气。现在,要求最外一圈都种上草,草地与荒地之间要用篱笆隔开,最少需要花费多少个力气?

题目分析:有篱笆要把草地和荒地隔开意味着把所有的块分成两个“阵营”。增加源点和汇点,用源点s代表草地“阵营”头领,汇点t代表荒地“阵营”头领,在初始时,从s向所有的草地(在边界处的除外)连一条弧,容量为d,表示该块草地要背叛头领s投奔敌人的代价;从所有的荒地向汇点连一条弧,容量为f,表示该块荒地放弃头领t的代价;对于任意一个块u,向所有与它相邻的v连一条弧,容量为b,表示u与v对立的代价。我们要做的就是用最少的代价这些块分成两个“阵营”,实际上就是求最小割。

CP:第一次用ISAP来写网络流。。。

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<queue>
# include<cstring>
# include<iostream>
using namespace std; const int INF=1<<30;
const int maxn=2505; int n,m;
char p[60][60]; struct Edge
{
int fr,to,cap,fw;
Edge(int fr,int to,int cap,int fw){
this->fr=fr;
this->to=to;
this->cap=cap;
this->fw=fw;
}
};
struct ISAP
{
vector<Edge>edges;
vector<int>G[maxn];
int d[maxn],gap[maxn],p[maxn];
int n,s,t,vis[maxn],cur[maxn]; void init(int n)
{
this->n=n;
edges.clear();
for(int i=0;i<n;++i) G[i].clear();
} void addEdge(int u,int v,int cap)
{
edges.push_back(Edge(u,v,cap,0));
edges.push_back(Edge(v,u,0,0));
int m=edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
} void bfs(int u)
{
memset(vis,0,sizeof(vis));
d[u]=0;
queue<int>q;
q.push(u);
vis[u]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=0;i<G[x].size();++i){
Edge &e=edges[G[x][i]];
if(e.cap>0) continue;
int v=edges[G[x][i]^1].fr;
if(!vis[v]){
vis[v]=1;
d[v]=d[x]+1;
q.push(v);
}
}
}
} int augment()
{
int a=INF;
for(int u=t;u!=s;u=edges[p[u]].fr){
Edge &e=edges[p[u]];
a=min(a,e.cap-e.fw);
}
for(int u=t;u!=s;u=edges[p[u]].fr){
edges[p[u]].fw+=a;
edges[p[u]^1].fw-=a;
}
return a;
} int maxFlow(int s,int t)
{
this->s=s,this->t=t;
bfs(t);
int flow=0;
memset(gap,0,sizeof(gap));
for(int i=0;i<n;++i) ++gap[d[i]];
memset(cur,0,sizeof(cur));
int x=s;
while(d[s]<n)
{
if(x==t){
flow+=augment();
x=s;
}
int flag=false;
for(int i=cur[x];i<G[x].size();++i){
Edge &e=edges[G[x][i]];
if(e.cap>e.fw&&d[x]==d[e.to]+1){
flag=true;
p[e.to]=G[x][i];
cur[x]=i;
x=e.to;
break;
}
}
if(!flag){
int m=n-1;
for(int i=0;i<G[x].size();++i){
Edge &e=edges[G[x][i]];
if(e.cap>e.fw) m=min(m,d[e.to]);
}
if((--gap[d[x]])==0) break;
d[x]=m+1;
++gap[d[x]];
cur[x]=0;
if(x!=s) x=edges[p[x]].fr;
}
}
return flow;
}
};
ISAP solver; int d,f,b;
int dd[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; bool ok(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int cnt=0;
scanf("%d%d",&m,&n);
scanf("%d%d%d",&d,&f,&b);
for(int i=1;i<=n;++i){
scanf("%s",p[i]+1);
if(p[i][1]=='.'){
++cnt;
p[i][1]='#';
}
if(m>1&&p[i][m]=='.'){
++cnt;
p[i][m]='#';
}
if(i==1||i==n)
for(int j=1;j<=m;++j)
if(p[i][j]=='.'){
++cnt;
p[i][j]='#';
}
}
solver.init(n*m+2);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
for(int k=0;k<4;++k){
int ni=i+dd[k][0],nj=j+dd[k][1];
if(ok(ni,nj)) solver.addEdge((i-1)*m+j,(ni-1)*m+nj,b);
}
if(p[i][j]=='#'){
if(i==1||i==n||j==1||j==m)
solver.addEdge(0,(i-1)*m+j,INF);
else
solver.addEdge(0,(i-1)*m+j,d);
}else{
solver.addEdge((i-1)*m+j,n*m+1,f);
}
}
}
printf("%d\n",solver.maxFlow(0,n*m+1)+cnt*f);
}
return 0;
}

  

UVA-1515 Pool construction (最小割)的更多相关文章

  1. Uva -1515 Pool construction(最小割)

    输入一个字符矩阵,'.'代表洞,'#'代表草地.可以把草改成洞花费为d,或者把洞改成草花费为f,最后还要在草和洞之间修围栏花费为b. 首先把最外一圈的洞变成草,并累加花费. 增加一个源点和一个汇点,源 ...

  2. UVA 1515 Pool construction 最大流跑最小割

    Pool construction You are working for the International Company for Pool Construction, a constructio ...

  3. UVa 1515 - Pool construction(最小割)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  4. UVALive 5905 Pool Construction 最小割,s-t割性质 难度:3

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  5. UVA 1515 Pool construction 水塘(最大流,经典)

    题意: 给一个h*w的矩阵,每个格子中是'#'和'.'两个符号之一,分别代表草和洞.现在要将洞给围起来(将草和洞分离),每条边需花费b元(即将一个洞包起来需要4边,将2个连续的洞包起来需要6边,省了2 ...

  6. UVA - 10480 Sabotage【最小割最大流定理】

    题意: 把一个图分成两部分,要把点1和点2分开.隔断每条边都有一个花费,求最小花费的情况下,应该切断那些边.这题很明显是最小割,也就是最大流.把1当成源点,2当成汇点,问题是要求最小割应该隔断那条边. ...

  7. UVa 1515 (最小割) Pool construction

    题意: 输入一个字符矩阵,'.'代表洞,'#'代表草地.可以把草改成洞花费为d,或者把洞改成草花费为f,最后还要在草和洞之间修围栏花费为b. 但要保证最外一圈是草,求最小费用. 分析: 还不是特别理解 ...

  8. 【uva 1515】Pool construction(图论--网络流最小割 模型题)

    题意:有一个水塘,要求把它用围栏围起来,每个费用为b.其中,(#)代表草,(.)代表洞,把一个草变成洞需要费用d, 把一个洞变成草需要费用f.请输出合法方案中的最小费用. 解法:(不好理解...... ...

  9. UVa1515 Pool construction(最小割)

    题目 Source https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

随机推荐

  1. 徐州网络赛H-Ryuji doesn't want to study【线段树】

    Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, ea ...

  2. Oracle体系结构之Oracle分区

    目录 Oracle分区 0 一.Oracle分区理论知识 1 二.分区表的实现方式 1 1.范围分区(range partition table) 1 2.列表分区(list partitioning ...

  3. talib 中文文档(七):Overlap Studies Functions

    Overlap Studies Functions 重叠指标 BBANDS - Bollinger Bands 函数名:BBANDS 名称: 布林线指标 简介:其利用统计原理,求出股价的标准差及其信赖 ...

  4. Rain on your Parade---hdu2389(HK求最大匹配)

    题目链接 题意:有n个客人,m把雨伞,在t秒之后将会下雨,给出每个客人的坐标和每秒行走的距离,以及雨伞的位置,问t秒后最多有几个客人可以拿到雨伞? 就是求最大匹配的  Hopcroft-Karp复杂度 ...

  5. 洛谷P5151 HKE与他的小朋友 快速幂/图论+倍增

    正解:矩阵快速幂/tarjan+倍增 解题报告: 传送门! 跟着神仙做神仙题系列III 这题首先一看到就会想到快速幂趴?就会jio得,哦也不是很难哦 然而,看下数据范围,,,1×105,,,显然开不下 ...

  6. iis启动&nbsp;服务无法在此时接受控制信息。&nbsp;(异常来自&nbsp;HRESULT:0x80070425)

    问题描述:每隔一段时间应用程序池就会自动停止,报错:服务无法在此时接受控制信息.(异常来自 HRESULT:0x80070425)   iis启动 服务无法在此时接受控制信息. (异常来自HRESUL ...

  7. SLAM FOR DUMMIES 第5-8章 中文翻译

    5,SLAM的处理过程 SLAM过程包括许多步骤,该过程的目标是使用环境更新机器人的位置.由于机器人的里程计通常是存在误差的,我们不能直接依赖于里程计.我们可以用激光扫描环境来校正机器人的位置,这是通 ...

  8. 布局-EasyUI Panel 面板、EasyUI Tabs 标签页/选项卡、EasyUI Accordion 折叠面板、EasyUI Layout 布局

    EasyUI Panel 面板 通过 $.fn.panel.defaults 重写默认的 defaults. 面板(panel)当做其他内容的容器使用.它是创建其他组件(比如:Layout 布局.Ta ...

  9. PhotoSwipe中文API(五)

    Responsive Images PhotoSwipe不支持<图片>或srcset,因为它要求所定义的图像的尺寸,并使用延迟加载.但是,随着图像动态加载,它很容易切换人士透露,即便是在旧 ...

  10. MapReduce的几个实现

    1.倒排索引的实现 import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.con ...