1. 程式人生 > >bzoj3171 [Tjoi2013]循環格

bzoj3171 [Tjoi2013]循環格

blog lru 多少 next url bits ora 元素 names

Description

技術分享圖片

Input

第一行兩個整數 \(R,C\) 。表示行和列,接下來 \(R\) 行,每行 \(C\) 個字符LRUD,表示左右上下。

Output

一個整數,表示最少需要修改多少個元素使得給定的循環格完美

Sample Input

3 4
RRRD
URLL
LRRR

Sample Output

2

HINT

\(1\le R,L\le 15\)

Solution

費用流。

顯然,構成完美循環格的條件是每個格子入度出度都是 \(1\)

考慮拆點,點 \(x\) 拆成 \(x_1\)\(x_2\) ,我們有 \[<S,x_1>:capacity=1;cost=0\]

\[<x_2,T>:capacity=1;cost=0\]

\(\forall x, y\) 四連通,有 \[<x_1,y_2>:capacity=1;cost=原圖中x是否不指向y\]

#include<bits/stdc++.h>
using namespace std;

#define N 500
#define INF 2000000000
#define rep(i, a, b) for (int i = a; i <= b; i++)

const int dx[] = { 1, 0, -1, 0 }, dy[] = { 0, 1, 0, -1 };

int n, m, a[N][N];
char
s[N][N]; int S, T, flow, cost; struct edge { int u, v, c, w, next; }e[10001]; int head[N], tot = 1; int dis[N], pre[N]; queue<int> q; bool inq[N]; inline void insert(int u, int v, int c, int w) { e[++tot].u = u, e[tot].v = v, e[tot].c = c, e[tot].w = w, e[tot].next = head[u], head[u] = tot; } inline
void add(int u, int v, int c, int w) { insert(u, v, c, w), insert(v, u, 0, -w); } inline bool spfa() { rep(i, S, T) dis[i] = INF; dis[S] = 0; q.push(S); while (!q.empty()) { int u = q.front(); q.pop(); inq[u] = 0; for (int i = head[u], v, w; i; i = e[i].next) if (e[i].c > 0 && dis[v = e[i].v] > dis[u] + (w = e[i].w)) { dis[v] = dis[u] + w, pre[v] = i; if (!inq[v]) q.push(v); inq[v] = 1; } } return dis[T] != INF; } inline void mcf() { int d = INF; for (int i = T; i != S; i = e[pre[i]].u) d = min(d, e[pre[i]].c); flow += d; for (int i = T; i != S; i = e[pre[i]].u) e[pre[i]].c -= d, e[pre[i] ^ 1].c += d, cost += d * e[pre[i]].w; } int main() { cin >> n >> m; T = n * m * 2 + 1; rep(i, 1, n) scanf("%s", s[i] + 1); rep(i, 1, n) rep(j, 1, m) { if (s[i][j] == 'U') a[i][j] = 2; else if (s[i][j] == 'R') a[i][j] = 1; else if (s[i][j] == 'L') a[i][j] = 3; } rep(i, 1, n) rep(j, 1, m) { int x1 = (i - 1) * m + j, x2 = x1 + n * m; add(S, x1, 1, 0), add(x2, T, 1, 0); rep(k, 0, 3) { int ni = i + dx[k], nj = j + dy[k]; if (ni < 1) ni = n; if (ni > n) ni = 1; if (nj < 1) nj = m; if (nj > m) nj = 1; int y1 = (ni - 1) * m + nj, y2 = y1 + n * m; add(x1, y2, 1, (int)(k != a[i][j])); } } while (spfa()) mcf(); cout << cost; return 0; }

bzoj3171 [Tjoi2013]循環格