UVa 1515 (最小割) Pool construction

题意:

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

但要保证最外一圈是草,求最小费用。

分析:

还不是特别理解紫书上的讲解。。

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

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

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

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

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

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

  1 #include <bits/stdc++.h>
  2
  3 using namespace std;
  4
  5 const int maxn = 50 * 50 + 10;
  6 const int INF = 1000000000;
  7
  8 struct Edge
  9 {
 10     int from, to, cap, flow;
 11 };
 12
 13 bool operator < (const Edge& a, const Edge& b)
 14 { return a.from < b.from || ( a.from == b.from && a.to < b.to ); }
 15
 16 struct Dinic
 17 {
 18     int n, m, s, t;
 19     vector<Edge> edges;
 20     vector<int> G[maxn];
 21     bool vis[maxn];    //BFS
 22     int d[maxn];    //起点到i的距离
 23     int cur[maxn];    //当前弧指针
 24
 25     int Init(int n)
 26     {
 27         for(int i = 0; i < n; ++i) G[i].clear();
 28         edges.clear();
 29     }
 30
 31     void AddEdge(int from, int to, int cap)
 32     {
 33         edges.push_back(Edge{from, to, cap, 0});
 34         edges.push_back(Edge{to, from, 0, 0});
 35         m = edges.size();
 36         G[from].push_back(m-2);
 37         G[to].push_back(m-1);
 38     }
 39
 40     bool BFS()
 41     {
 42         memset(vis, false, sizeof(vis));
 43         queue<int> Q;
 44         Q.push(s);
 45         vis[s] = true;
 46         d[s] = 0;
 47         while(!Q.empty())
 48         {
 49             int x = Q.front(); Q.pop();
 50             for(int i = 0; i < G[x].size(); ++i)
 51             {
 52                 Edge& e = edges[G[x][i]];
 53                 if(!vis[e.to] && e.cap > e.flow)
 54                 {
 55                     vis[e.to] = true;
 56                     d[e.to] = d[x] + 1;
 57                     Q.push(e.to);
 58                 }
 59             }
 60         }
 61         return vis[t];
 62     }
 63
 64     int DFS(int x, int a)
 65     {
 66         if(x == t || a == 0) return a;
 67         int flow = 0, f;
 68         for(int& i = cur[x]; i < G[x].size(); ++i)
 69         {
 70             Edge& e = edges[G[x][i]];
 71             if(d[x] + 1 ==d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0)
 72             {
 73                 e.flow += f;
 74                 edges[G[x][i]^1].flow -= f;
 75                 flow += f;
 76                 a -= f;
 77                 if(a == 0) break;
 78             }
 79         }
 80         return flow;
 81     }
 82
 83     int MaxFlow(int s, int t)
 84     {
 85         this->s = s; this->t = t;
 86         int flow = 0;
 87         while(BFS())
 88         {
 89             memset(cur, 0, sizeof(cur));
 90             flow += DFS(s, INF);
 91         }
 92         return flow;
 93     }
 94 }g;
 95
 96 int w, h;
 97 char pool[99][99];
 98
 99 inline int ID(int i, int j) { return i*w+j; }
100
101 int main()
102 {
103     //freopen("in.txt", "r", stdin);
104
105     int T, d, f, b;
106     scanf("%d", &T);
107     while(T--)
108     {
109         scanf("%d%d%d%d%d", &w, &h, &d, &f, &b);
110         for(int i = 0; i < h; ++i) scanf("%s", pool[i]);
111         int cost = 0;
112         for(int i = 0; i < h; ++i)//把边上的洞填成草
113         {
114             if(pool[i][0] == ‘.‘) { pool[i][0] = ‘#‘; cost += f; }
115             if(pool[i][w-1] == ‘.‘) { pool[i][w-1] = ‘#‘; cost += f; }
116         }
117         for(int i = 0; i < w; ++i)
118         {
119             if(pool[0][i] == ‘.‘) { pool[0][i] = ‘#‘; cost += f; }
120             if(pool[h-1][i] == ‘.‘) { pool[h-1][i] = ‘#‘; cost += f; }
121         }
122
123         g.Init(h*w+2);
124         for(int i = 0; i < h; i++)
125             for(int j = 0; j < w; j++)
126             {
127                 if(pool[i][j] == ‘#‘)
128                 {
129                     int cap = d;
130                     if(i == 0 || i == h-1 || j == 0 || j == w-1) cap = INF;
131                     g.AddEdge(w*h, ID(i, j), cap);
132                 }
133                 else
134                 {
135                     g.AddEdge(ID(i, j), w*h+1, f);
136                 }
137                 if(i > 0) g.AddEdge(ID(i, j), ID(i-1, j), b);
138                 if(i < h-1) g.AddEdge(ID(i, j), ID(i+1, j), b);
139                 if(j > 0) g.AddEdge(ID(i, j), ID(i, j-1), b);
140                 if(j < w-1) g.AddEdge(ID(i, j), ID(i, j+1), b);
141             }
142
143         printf("%d\n", cost + g.MaxFlow(w*h, w*h+1));
144     }
145
146     return 0;
147 }

代码君

时间: 2024-10-16 21:27:57

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

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>

Uva -1515 Pool construction(最小割)

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

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 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 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 Frequency Hopping (最大流+最小割)

题意:与正常的网络流一样,不过给定的第一行的最后一个数C的意思是能能否在给定的图里求出修改某一条边或者不修改某一条边是的这个图的流变成C,如果没修改就能有C,那么输出possible,通过修改能得到C输出possible+能修改的边集合,否则输出no possible 思路:(自己的是死暴力方法,直接爆了,想了很多法子都来不起,最后参照白书的思路来起了)可以先求出最大流,然后求出最小割里的弧,依次修改最小割里的弧,看能求出的最大流是否大于C PS:不优化的话很容易超时,第一个优化是把第一次求得得