bzoj3171 [Tjoi2013]循环格

Posted aziint

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3171 [Tjoi2013]循环格相关的知识,希望对你有一定的参考价值。

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]循环格的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3171 [Tjoi2013]循环格(MCMF)

bzoj 3171: [Tjoi2013]循环格

BZOJ 3171 [Tjoi2013]循环格

bzoj3171 [Tjoi2013]循环格

bzoj:3171: [Tjoi2013]循环格

bzoj3171: [Tjoi2013]循环格