标签:
http://acm.hdu.edu.cn/showproblem.php?pid=4859
这题考察的是最小割。
我们可以这样想:海岸线的长短变化都是E引起的,我们通过把’E‘变成‘.‘或‘D‘来使海岸线最大化。
我们要算海岸线就是算格子‘.‘和格子‘D‘(在原有地图周围四面都要加’D‘)相邻的面数,要使它最大,就是要使‘.‘与’.‘;‘D‘与‘D‘相邻的面数最小,而面数最小可以用最小割来做。
现在我们先把格子上的点黑白染色,(i+j)%2==1的为A类,为0的为B类,
在A类中,所的’.‘与源点相连(容量为INF),所有的’D‘与汇点相连(容量为INF)。
在B类中,所有的‘.‘与汇点相连(容量为INF),所有的‘D‘与源点相连(容量为INF)。
E不与源点,汇点相连。
所有的点与周围的四个点连一条有向边(容量为1)。
图建好啦,跑一下最大流,ans=总的面-最大流。
现在让我们来研究一下这图的一些性质:
首先,只有’.‘到‘.‘,’D‘到‘D‘的路径能联通源点汇点
其次,考虑‘E‘。
如果与‘E’相连的四个点都是‘.‘或都是‘D‘,那这个’E‘,不可能有流通过,也就是它最终的属性肯定与周围的是相反的!
其次如果与‘E‘相邻的有’.‘和‘D‘(这里的‘.‘和’D‘要么都属于A类,要么都属于B类),那么就可能会有不同的流通过(这就是在给E定属性了)。
我们通过最大流算法求出图的最小割,也就是两边相同的面数的最小值。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn = 55; const int INF=0x3f3f3f3f; struct Edge { int from, to, cap, flow; Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){} }; struct Dinic { int n, m, s, t; vector<Edge> edges; vector<int> G[maxn*maxn]; bool vis[maxn*maxn]; int d[maxn*maxn]; int cur[maxn*maxn]; void init(int n) { this->n = n; for (int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void addEdge(int from, int to, int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); d[s] = 0; vis[s] = 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 (!vis[e.to] && e.cap>e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if (x == t || a == 0) return a; int flow = 0, f; for (int& i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0) { e.flow += f; edges[G[x][i] ^ 1].flow -= f; flow += f; a -= f; if (a == 0) break; } } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while (BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } }dinic; char str[maxn][maxn]; int mp[maxn][maxn]; int n, m,tot; const int dx[] = { -1,1,0,0 }; const int dy[] = { 0,0,-1,1 }; void init() { tot = 1; } int main() { int tc,kase=0; scanf("%d", &tc); while (tc--) { scanf("%d%d", &n,&m); init(); for (int i = 1; i <= n; i++) { scanf("%s", str[i]+1); } n++, m++; for (int i = 0; i <= n; i++) str[i][0] = str[i][m] = ‘D‘; for (int j = 0; j <= m; j++) str[0][j] = str[n][j] = ‘D‘; for (int i = 0; i <= n; i++) { for (int j = 0; j <= m; j++) { mp[i][j] = tot++; } } dinic.init(tot+1); for (int i = 0; i <= n; i++) { for (int j = 0; j <= m; j++) { for (int k = 0; k < 4; k++) { int x = i + dx[k], y = j + dy[k]; if (x < 0 || x > n || y < 0 || y > m) continue; dinic.addEdge(mp[i][j], mp[x][y],1); } if ((i + j) % 2) { if (str[i][j] == ‘.‘) { dinic.addEdge(mp[i][j], tot, INF); } else if (str[i][j] == ‘D‘) { dinic.addEdge(0, mp[i][j], INF); } } else { if (str[i][j] == ‘.‘) { dinic.addEdge(0, mp[i][j], INF); } else if(str[i][j]==‘D‘) { dinic.addEdge(mp[i][j], tot, INF); } } } } int tmp = dinic.Maxflow(0, tot); int ans = (n+1)*(m+1)*2-(m+1)-(n+1)-tmp; printf("Case %d: %d\n",++kase, ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/fenice/p/5557942.html