Uva -1515 Pool construction(最小割)

输入一个字符矩阵,‘.‘代表洞,‘#‘代表草地。可以把草改成洞花费为d,或者把洞改成草花费为f,最后还要在草和洞之间修围栏花费为b。

首先把最外一圈的洞变成草,并累加花费。

增加一个源点和一个汇点,源点连接每个草地,汇点连接每个洞。

源点与最外一圈的草地连一条容量无穷大的边,与其他草地连一条容量为d的边。表示把这条弧切断,割的容量增加d,草就会变成洞。

每个洞与汇点连一条容量为f的边。

相邻两个格子之间连一条双向边。

用最大流算法求最小割在加上之前把边界上的洞变成草的费用,就是最小花费。

用最小的费用将对象划分成两个集合的问题常常可以转换成最小割顺利解决.这道题就可以考虑将每一个点变成草地和洞分成两个集合.

如果通过合适的建边使得花费的总和等价于割的容量的话,那么为了求最小花费只要求最小割就好.

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <vector>
  5 #include <cstring>
  6 #include <string>
  7 #include <algorithm>
  8 #include <string>
  9 #include <set>
 10 #include <functional>
 11 #include <numeric>
 12 #include <sstream>
 13 #include <stack>
 14 #include <map>
 15 #include <queue>
 16 #pragma comment(linker, "/STACK:102400000,102400000")
 17 #define CL(arr, val)    memset(arr, val, sizeof(arr))
 18
 19 #define ll long long
 20 #define inf 0x7f7f7f7f
 21 #define lc l,m,rt<<1
 22 #define rc m + 1,r,rt<<1|1
 23 #define pi acos(-1.0)
 24
 25 #define L(x)    (x) << 1
 26 #define R(x)    (x) << 1 | 1
 27 #define MID(l, r)   (l + r) >> 1
 28 #define Min(x, y)   (x) < (y) ? (x) : (y)
 29 #define Max(x, y)   (x) < (y) ? (y) : (x)
 30 #define E(x)        (1 << (x))
 31 #define iabs(x)     (x) < 0 ? -(x) : (x)
 32 #define OUT(x)  printf("%I64d\n", x)
 33 #define lowbit(x)   (x)&(-x)
 34 #define Read()  freopen("a.txt", "r", stdin)
 35 #define Write() freopen("b.txt", "w", stdout);
 36 #define maxn 1010
 37 #define maxv 3000
 38 #define mod 1000000000
 39 using namespace std;
 40
 41 struct edge
 42 {
 43     int to,cap,rev;
 44     edge(){}
 45     edge(int x,int y,int z)
 46     {
 47         to=x;
 48         cap=y;
 49         rev=z;
 50     }
 51 };
 52
 53 vector<edge>G[maxv];
 54 int level[maxv];
 55 int iter[maxv];
 56
 57 void Add_Edge(int from,int to,int cap)
 58 {
 59     G[from].push_back((edge){to,cap,G[to].size()});
 60     G[to].push_back((edge){from,0,G[from].size()-1});
 61 }
 62
 63 void bfs(int s)
 64 {
 65     memset(level,-1,sizeof(level));
 66     queue<int>que;
 67     level[s]=0;
 68     que.push(s);
 69     while(!que.empty())
 70     {
 71         int v=que.front();que.pop();
 72         for(int i=0;i<G[v].size();i++)
 73         {
 74             edge &e=G[v][i];
 75             if(e.cap>0&&level[e.to]<0)
 76             {
 77                 level[e.to]=level[v]+1;
 78                 que.push(e.to);
 79             }
 80         }
 81     }
 82 }
 83 int dfs(int v,int t,int f)
 84 {
 85     if(v==t) return f;
 86     for(int &i=iter[v];i<G[v].size();i++)
 87     {
 88         edge &e=G[v][i];
 89         if(e.cap>0&&level[v]<level[e.to])
 90         {
 91             int d=dfs(e.to,t,min(f,e.cap));
 92             if(d>0)
 93             {
 94                 e.cap-=d;
 95                 G[e.to][e.rev].cap+=d;
 96               //  printf("%d %d %d\n",e.to,e.rev,G[e.to][e.rev]);
 97                 return d;
 98             }
 99         }
100     }
101     return 0;
102 }
103
104 int max_flow(int s,int t)
105 {
106     int flow=0;
107     for(;;)
108     {
109         bfs(s);
110         if(level[t]<0) return flow;
111         memset(iter,0,sizeof(iter));
112         int f;
113         while((f=dfs(s,t,inf))>0)
114         flow+=f;
115     }
116 }
117 char s[55][55];
118 int w,h;
119 int ID(int i,int j)
120 {
121     return i*w+j;
122 }
123 int main()
124 {
125     //freopen("a.txt","r",stdin);
126     int t,d,f,b;
127     scanf("%d",&t);
128     while(t--)
129     {
130         scanf("%d%d%d%d%d",&w,&h,&d,&f,&b);
131         for(int i=0;i<w*h+2;i++)
132             G[i].clear();
133         for(int i=0;i<h;i++)
134         {
135             scanf("%s",s[i]);
136         }
137         int cost=0;
138         for(int i=0;i<h;i++)
139         {
140             if(s[i][0]==‘.‘) {s[i][0]=‘#‘;cost+=f;}
141             if(s[i][w-1]==‘.‘) {s[i][w-1]=‘#‘;cost+=f;}
142         }
143         for(int i=0;i<w;i++)
144         {
145             if(s[0][i]==‘.‘) {s[0][i]=‘#‘;cost+=f;}
146             if(s[h-1][i]==‘.‘){s[h-1][i]=‘#‘;cost+=f;}
147         }
148         for(int i=0;i<h;i++)
149         {
150             for(int j=0;j<w;j++)
151             {
152                 if(s[i][j]==‘#‘)
153                 {
154                     int cap=inf;
155                     if(i>0&&i<h-1&&j>0&&j<w-1) cap=d;
156                     Add_Edge(w*h,ID(i,j),cap);
157                     if(i>0) {Add_Edge(ID(i,j),ID(i-1,j),b);}
158                     if(i<h-1) {Add_Edge(ID(i,j),ID(i+1,j),b);}
159                     if(j>0) {Add_Edge(ID(i,j),ID(i,j-1),b);}
160                     if(j<w-1) {Add_Edge(ID(i,j),ID(i,j+1),b);}
161                 }
162                 else
163                 {
164                     Add_Edge(ID(i,j),w*h+1,f);
165                     if(i>0) {Add_Edge(ID(i,j),ID(i-1,j),b);}
166                     if(i<h-1) {Add_Edge(ID(i,j),ID(i+1,j),b);}
167                     if(j>0) {Add_Edge(ID(i,j),ID(i,j-1),b);}
168                     if(j<w-1) {Add_Edge(ID(i,j),ID(i,j+1),b);}
169                 }
170             }
171         }
172         printf("%d\n",cost+max_flow(w*h,w*h+1));
173     }
174     return 0;
175 }
时间: 2024-08-05 15:16:46

Uva -1515 Pool construction(最小割)的相关文章

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

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3916 这道题要求一种填充+挖坑+建屏障的方法,使得这块土地上的所有坑和草地之间都有屏障,挖坑花费d每块,填充花费f每块,建屏障花费b每两块之间,注意并不要求一定有坑,但是外围一圈要一定没有坑,所以需要预先填充好 令st代表平地,ed代表坑,边权为花费,那么本题是要求一个st-

UVa1515 Pool construction (最小割)

链接:http://vjudge.net/problem/UVA-1515 分析:首先分析一个特例,如果草地“#”和洞“.”不允许相互转化,那么我们可以直接从草地‘#”出发向图中相邻洞格子“.”连一条容量为b的弧,源点S向所有草地“#”连一条弧,所有洞“.”向汇点T连一条弧,容量均为无穷大,那么最小割就是建围栏的总费用. 这道题在上述基础上加了草地和洞可以相互转化这一条件.根据刚才的思路,我们可以联想到,只要草地“#”转化成洞“.”的时候,就不需要在它和周围的洞“.”之间建围栏了,那么我们可以限

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

题意:给一个h*w的矩阵,每个格子中是'#'和'.'两个符号之一,分别代表草和洞.现在要将洞给围起来(将草和洞分离),每条边需花费b元(即将一个洞包起来需要4边,将2个连续的洞包起来需要6边,省了2条边).有个特殊能力,能将洞变成草,花费f.当然也能将草变成洞,花费d.围起洞来需要多少花费.矩阵四周最边边的格子都必须是草,即出现洞就必须转草. 转换:洞--->草--->洞  f   d   元/格 围洞: b元/边. 分析:如果能够尽量让洞都靠在一起,那肯定是最小花费,因为少了很多条边.但是转

UVA 1212 - Duopoly(最小割)

UVA 1212 - Duopoly 题目链接 题意:两个公司,每个公司都有n个开价租用一些频道,一个频道只能租给一个公司,现在要求出一个分配方案使得收益最大 思路:最小割,源点连到第一个公司,第二个公司连到汇点,容量均为价钱,然后第一个公司和第二个公司有冲突的就连一条边容量为无穷大,然后求这个图的最小割就是去掉最小多少使得图原图不会冲突了,然后用总金额减去最小割的值即可 代码: #include <cstdio> #include <cstring> #include <q

uva 1212 Duopoly (最小割最大流)

uva 1212 Duopoly Description The mobile network market in country XYZ used to be dominated by two large corporations, XYZ Telecom and XYZ Mobile. The central government recently has realized that radio frequency spectrum is a scarce resource and want

UVa 1515 (最小割) Pool construction

题意: 输入一个字符矩阵,'.'代表洞,'#'代表草地.可以把草改成洞花费为d,或者把洞改成草花费为f,最后还要在草和洞之间修围栏花费为b. 但要保证最外一圈是草,求最小费用. 分析: 还不是特别理解紫书上的讲解.. 首先把最外一圈的洞变成草,并累加花费. 增加一个源点和一个汇点,源点连接每个草地,汇点连接每个洞. 源点与最外一圈的草地连一条容量无穷大的边,与其他草地连一条容量为d的边.表示把这条弧切断,割的容量增加d,草就会变成洞. 每个洞与汇点连一条容量为f的边. 相邻两个格子之间连一条双向

UVA 11419 SAM I AM (二分图,最小割)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2414 Problem C SAM I AM Input: Standard Input Output: Standard Output The world is in great danger!! Mental's forces have returned to Earth to eradi

UVA - 10480 Sabotage 最小割,输出割法

UVA - 10480 Sabotage 题意:现在有n个城市,m条路,现在要把整个图分成2部分,编号1,2的城市分成在一部分中,拆开每条路都需要花费,现在问达成目标的花费最少要隔开那几条路. 题解:建图直接按给你的图建一下,然后呢跑一下最大流,我们就知道了最小割是多少,答案就是最小割了  . 现在要求输出割法.我们从s开始往前跑,如果某条正向边有流量,我们就按着这条边继续往外走,知道无法再走,把所有经历过的点都染一下色.最后看所有的边,是不是有一头是染色了,另一头没有染色,如果是,这条边就是割

uva 11248 最小割

Dinic 1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstdio> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<cstring> 10 #include<stack>