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

 

你可能感兴趣的:(struct)