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 }
代码君

 

posted @ 2015-02-17 10:58  AOQNRMGYXLMV  阅读(313)  评论(0编辑  收藏  举报